diff --git a/eng/pipelines/common/templates/wasm-library-aot-tests.yml b/eng/pipelines/common/templates/wasm-library-aot-tests.yml index 2bf45172a9277b..d3dbf8d8db6524 100644 --- a/eng/pipelines/common/templates/wasm-library-aot-tests.yml +++ b/eng/pipelines/common/templates/wasm-library-aot-tests.yml @@ -35,9 +35,7 @@ jobs: - ${{ if ne(parameters.scenarios[0], '') }}: - ${{ parameters.scenarios }} - ${{ else }}: - - ${{ if eq(platform, 'browser_wasm') }}: - - WasmTestOnV8 - - ${{ if eq(platform, 'browser_wasm_win') }}: + - ${{ if or(eq(platform, 'browser_wasm'), eq(platform, 'browser_wasm_win')) }}: - WasmTestOnChrome - ${{ if or(eq(platform, 'wasi_wasm_win'), eq(platform, 'wasi_wasm')) }}: - WasmTestOnWasmtime diff --git a/eng/pipelines/common/templates/wasm-library-tests.yml b/eng/pipelines/common/templates/wasm-library-tests.yml index f015563fef00e3..51cf40074ff5bd 100644 --- a/eng/pipelines/common/templates/wasm-library-tests.yml +++ b/eng/pipelines/common/templates/wasm-library-tests.yml @@ -6,7 +6,7 @@ parameters: isWasmOnlyBuild: false nameSuffix: '' platforms: [] - scenarios: ['WasmTestOnV8'] + scenarios: ['WasmTestOnChrome'] shouldContinueOnError: false shouldRunSmokeOnly: false diff --git a/eng/pipelines/extra-platforms/runtime-extra-platforms-wasm.yml b/eng/pipelines/extra-platforms/runtime-extra-platforms-wasm.yml index 259982aff35451..236cd8c9278e6c 100644 --- a/eng/pipelines/extra-platforms/runtime-extra-platforms-wasm.yml +++ b/eng/pipelines/extra-platforms/runtime-extra-platforms-wasm.yml @@ -89,7 +89,6 @@ jobs: isExtraPlatformsBuild: ${{ parameters.isExtraPlatformsBuild }} isWasmOnlyBuild: ${{ parameters.isWasmOnlyBuild }} scenarios: - - WasmTestOnV8 - WasmTestOnChrome # EAT Library tests - only run on linux diff --git a/eng/pipelines/libraries/outerloop-mono.yml b/eng/pipelines/libraries/outerloop-mono.yml index b9d4bcfecd7b27..329de2ea9267e3 100644 --- a/eng/pipelines/libraries/outerloop-mono.yml +++ b/eng/pipelines/libraries/outerloop-mono.yml @@ -65,7 +65,7 @@ extends: - template: /eng/pipelines/libraries/helix.yml parameters: scenarios: - - WasmTestOnV8 + - WasmTestOnChrome testScope: outerloop creator: dotnet-bot testRunNamePrefixSuffix: Mono_$(_BuildConfig) diff --git a/eng/pipelines/runtime.yml b/eng/pipelines/runtime.yml index 26d80a53ab5100..2e68a43af682ef 100644 --- a/eng/pipelines/runtime.yml +++ b/eng/pipelines/runtime.yml @@ -823,7 +823,6 @@ extends: alwaysRun: ${{ variables.isRollingBuild }} extraBuildArgs: /p:AotHostArchitecture=x64 /p:AotHostOS=$(_hostedOS) scenarios: - - WasmTestOnV8 - WasmTestOnChrome - WasmTestOnFirefox diff --git a/eng/testing/scenarios/BuildWasmAppsJobsList.txt b/eng/testing/scenarios/BuildWasmAppsJobsList.txt index 818ff9e8edd3c2..f94f6fbcaa6c1d 100644 --- a/eng/testing/scenarios/BuildWasmAppsJobsList.txt +++ b/eng/testing/scenarios/BuildWasmAppsJobsList.txt @@ -48,5 +48,4 @@ Wasm.Build.Tests.WasmSIMDTests Wasm.Build.Tests.WasmTemplateTests Wasm.Build.Tests.WorkloadTests Wasm.Build.Tests.MT.Blazor.SimpleMultiThreadedTests -Wasm.Build.Tests.TestAppScenarios.WasmSdkDebugLevelTests -Wasm.Build.Tests.TestAppScenarios.WasmAppBuilderDebugLevelTests +Wasm.Build.Tests.DebugLevelTests diff --git a/src/mono/wasm/Wasm.Build.Tests/Blazor/BlazorWasmProjectProvider.cs b/src/mono/wasm/Wasm.Build.Tests/Blazor/BlazorWasmProjectProvider.cs index 5d8a6d578f20fb..f715ece03bd553 100644 --- a/src/mono/wasm/Wasm.Build.Tests/Blazor/BlazorWasmProjectProvider.cs +++ b/src/mono/wasm/Wasm.Build.Tests/Blazor/BlazorWasmProjectProvider.cs @@ -1,6 +1,7 @@ // 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.Abstractions; #nullable enable @@ -9,9 +10,9 @@ namespace Wasm.Build.Tests; public class BlazorWasmProjectProvider : WasmSdkBasedProjectProvider { - public BlazorWasmProjectProvider(ITestOutputHelper _testOutput, string? _projectDir = null) - : base(_testOutput, _projectDir) - {} + public BlazorWasmProjectProvider(ITestOutputHelper _testOutput, string defaultTargetFramework, string? _projectDir = null) + : base(_testOutput, defaultTargetFramework, _projectDir) + { } public void AssertBundle(BlazorBuildOptions options) => AssertBundle(new AssertWasmSdkBundleOptions( diff --git a/src/mono/wasm/Wasm.Build.Tests/Blazor/BlazorWasmTestBase.cs b/src/mono/wasm/Wasm.Build.Tests/Blazor/BlazorWasmTestBase.cs index e2406c873b986c..75769e5da3cbc8 100644 --- a/src/mono/wasm/Wasm.Build.Tests/Blazor/BlazorWasmTestBase.cs +++ b/src/mono/wasm/Wasm.Build.Tests/Blazor/BlazorWasmTestBase.cs @@ -15,14 +15,13 @@ namespace Wasm.Build.Tests; -public abstract class BlazorWasmTestBase : WasmTemplateTestBase +public abstract class BlazorWasmTestBase : WasmTemplateTestsBase { protected readonly BlazorWasmProjectProvider _provider; protected BlazorWasmTestBase(ITestOutputHelper output, SharedBuildPerTestClassFixture buildContext) - : base(output, buildContext, new BlazorWasmProjectProvider(output)) + : base(output, buildContext, new BlazorWasmProjectProvider(output, DefaultTargetFrameworkForBlazor)) { _provider = GetProvider(); - _provider.BundleDirName = "wwwroot"; } public void InitBlazorWasmProjectDir(string id, string targetFramework = DefaultTargetFrameworkForBlazor) @@ -250,10 +249,4 @@ void OnErrorMessage(string msg) public string FindBlazorBinFrameworkDir(string config, bool forPublish, string framework = DefaultTargetFrameworkForBlazor, string? projectDir = null) => _provider.FindBinFrameworkDir(config: config, forPublish: forPublish, framework: framework, projectDir: projectDir); - - public string FindBlazorHostedBinFrameworkDir(string config, bool forPublish, string clientDirRelativeToProjectDir, string framework = DefaultTargetFrameworkForBlazor) - { - string? clientProjectDir = _projectDir == null ? null : Path.Combine(_projectDir, clientDirRelativeToProjectDir); - return _provider.FindBinFrameworkDir(config: config, forPublish: forPublish, framework: framework, projectDir: clientProjectDir); - } } diff --git a/src/mono/wasm/Wasm.Build.Tests/BrowserRunner.cs b/src/mono/wasm/Wasm.Build.Tests/BrowserRunner.cs index eeef8b4c66672b..0b6b7d3dda4130 100644 --- a/src/mono/wasm/Wasm.Build.Tests/BrowserRunner.cs +++ b/src/mono/wasm/Wasm.Build.Tests/BrowserRunner.cs @@ -18,6 +18,8 @@ internal class BrowserRunner : IAsyncDisposable { private static Regex s_blazorUrlRegex = new Regex("Now listening on: (?https?://.*$)"); private static Regex s_appHostUrlRegex = new Regex("^App url: (?https?://.*$)"); + private static Regex s_appPublishedUrlRegex = new Regex(@"^\s{2}(?https?://.*$)"); + private static readonly Regex s_payloadRegex = new Regex("\"payload\":\"(?[^\"]*)\"", RegexOptions.Compiled); private static Regex s_exitRegex = new Regex("WASM EXIT (?-?[0-9]+)$"); private static readonly Lazy s_chromePath = new(() => { @@ -52,9 +54,15 @@ public async Task StartServerAndGetUrlAsync( OutputLines.Add(msg); } - Match m = s_appHostUrlRegex.Match(msg); - if (!m.Success) - m = s_blazorUrlRegex.Match(msg); + var regexes = new[] { s_appHostUrlRegex, s_blazorUrlRegex, s_appPublishedUrlRegex }; + Match m = Match.Empty; + + foreach (var regex in regexes) + { + m = regex.Match(msg); + if (m.Success) + break; + } if (m.Success) { @@ -176,8 +184,36 @@ public async Task RunAsync( IPage page = await context.NewPageAsync(); - if (onConsoleMessage is not null) - page.Console += (_, msg) => onConsoleMessage(page, msg); + page.Console += (_, msg) => + { + string message = msg.Text; + Match payloadMatch = s_payloadRegex.Match(message); + if (payloadMatch.Success) + { + message = payloadMatch.Groups["payload"].Value; + } + if (message.StartsWith("TestOutput -> ")) + { + lock (OutputLines) + { + OutputLines.Add(message); + } + } + Match exitMatch = s_exitRegex.Match(message); + if (exitMatch.Success) + { + lock (OutputLines) + { + OutputLines.Add(message); + } + int exitCode = int.Parse(exitMatch.Groups["exitCode"].Value); + _exited.TrySetResult(exitCode); + } + if (onConsoleMessage is not null) + { + onConsoleMessage(page, msg); + } + }; onError ??= _testOutput.WriteLine; if (onError is not null) diff --git a/src/mono/wasm/Wasm.Build.Tests/BuildTestBase.cs b/src/mono/wasm/Wasm.Build.Tests/BuildTestBase.cs index 33221e26679079..b61f4b13cf9220 100644 --- a/src/mono/wasm/Wasm.Build.Tests/BuildTestBase.cs +++ b/src/mono/wasm/Wasm.Build.Tests/BuildTestBase.cs @@ -198,6 +198,9 @@ public BuildTestBase(ProjectProviderBase providerBase, ITestOutputHelper output, return (res, logFilePath); } + protected bool IsDotnetWasmFromRuntimePack(BuildArgs buildArgs) => + !(buildArgs.AOT || (buildArgs.Config == "Release" && IsUsingWorkloads)); + protected string RunAndTestWasmApp(BuildArgs buildArgs, RunHost host, string id, diff --git a/src/mono/wasm/Wasm.Build.Tests/Common/AssertTestMainJsAppBundleOptions.cs b/src/mono/wasm/Wasm.Build.Tests/Common/AssertTestMainJsAppBundleOptions.cs index 3f0188b06e20f6..2924281dbdc433 100644 --- a/src/mono/wasm/Wasm.Build.Tests/Common/AssertTestMainJsAppBundleOptions.cs +++ b/src/mono/wasm/Wasm.Build.Tests/Common/AssertTestMainJsAppBundleOptions.cs @@ -23,7 +23,7 @@ public record AssertTestMainJsAppBundleOptions( bool AssertSymbolsFile = true, bool HasV8Script = false, bool IsBrowserProject = true) - : AssertBundleOptionsBase( + : AssertWasmSdkBundleOptions( Config: Config, IsPublish: IsPublish, TargetFramework: TargetFramework, @@ -32,7 +32,7 @@ public record AssertTestMainJsAppBundleOptions( GlobalizationMode: GlobalizationMode, ExpectedFileType: ExpectedFileType, RuntimeType: RuntimeType, - BootJsonFileName: BootJsonFileName, + BootConfigFileName: BootJsonFileName, ExpectFingerprintOnDotnetJs: ExpectFingerprintOnDotnetJs, ExpectSymbolsFile: ExpectSymbolsFile, AssertIcuAssets: AssertIcuAssets, diff --git a/src/mono/wasm/Wasm.Build.Tests/AssertWasmSdkBundleOptions.cs b/src/mono/wasm/Wasm.Build.Tests/Common/AssertWasmSdkBundleOptions.cs similarity index 100% rename from src/mono/wasm/Wasm.Build.Tests/AssertWasmSdkBundleOptions.cs rename to src/mono/wasm/Wasm.Build.Tests/Common/AssertWasmSdkBundleOptions.cs diff --git a/src/mono/wasm/Wasm.Build.Tests/ConfigSrcTests.cs b/src/mono/wasm/Wasm.Build.Tests/ConfigSrcTests.cs index 6c525fa4eab22c..e971485b91ef44 100644 --- a/src/mono/wasm/Wasm.Build.Tests/ConfigSrcTests.cs +++ b/src/mono/wasm/Wasm.Build.Tests/ConfigSrcTests.cs @@ -26,7 +26,7 @@ public void ConfigSrcAbsolutePath(BuildArgs buildArgs, RunHost host, string id) id: id, new BuildProjectOptions( InitProject: () => File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), s_mainReturns42), - DotnetWasmFromRuntimePack: !(buildArgs.AOT || buildArgs.Config == "Release"))); + DotnetWasmFromRuntimePack: IsDotnetWasmFromRuntimePack(buildArgs))); string binDir = GetBinDir(baseDir: _projectDir!, config: buildArgs.Config); string bundleDir = Path.Combine(binDir, "AppBundle"); diff --git a/src/mono/wasm/Wasm.Build.Tests/DebugLevelTests.cs b/src/mono/wasm/Wasm.Build.Tests/DebugLevelTests.cs new file mode 100644 index 00000000000000..8fc90b9376ec59 --- /dev/null +++ b/src/mono/wasm/Wasm.Build.Tests/DebugLevelTests.cs @@ -0,0 +1,125 @@ +// 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.Linq; +using System.Threading.Tasks; +using Xunit; +using Xunit.Abstractions; +using Wasm.Build.Tests.TestAppScenarios; + +#nullable enable + +namespace Wasm.Build.Tests; + +// ToDo: fix to be based on WasmTemplateTestBase +public class DebugLevelTests : AppTestBase +{ + public DebugLevelTests(ITestOutputHelper output, SharedBuildPerTestClassFixture buildContext) + : base(output, buildContext) + { + } + + private void AssertDebugLevel(string result, int value) + => Assert.Contains($"WasmDebugLevel: {value}", result); + + private BuildProjectOptions GetProjectOptions(bool isPublish = false) => + new BuildProjectOptions( + DotnetWasmFromRuntimePack: !isPublish, + CreateProject: false, + MainJS: "main.js", + HasV8Script: false, + Publish: isPublish, + AssertAppBundle: false, + UseCache: false + ); + + private string BuildPublishProject(string projectName, string config, bool isPublish = false, params string[] extraArgs) + { + var buildArgs = new BuildArgs(projectName, config, false, projectName, null); + buildArgs = ExpandBuildArgs(buildArgs); + (string _, string output) = BuildTemplateProject(buildArgs, + buildArgs.Id, + GetProjectOptions(isPublish), + extraArgs: extraArgs + ); + return output; + } + + [Theory] + [InlineData("Debug")] + [InlineData("Release")] + public async Task BuildWithDefaultLevel(string configuration) + { + string testAssetName = "WasmBasicTestApp"; + string projectFile = $"{testAssetName}.csproj"; + CopyTestAsset(testAssetName, $"DebugLevelTests_BuildWithDefaultLevel_{configuration}", "App"); + BuildPublishProject(projectFile, configuration); + + string result = await RunBuiltBrowserApp(configuration, projectFile, testScenario: "DebugLevelTest"); + AssertDebugLevel(result, -1); + } + + [Theory] + [InlineData("Debug", 1)] + [InlineData("Release", 1)] + [InlineData("Debug", 0)] + [InlineData("Release", 0)] + public async Task BuildWithExplicitValue(string configuration, int debugLevel) + { + string testAssetName = "WasmBasicTestApp"; + string projectFile = $"{testAssetName}.csproj"; + CopyTestAsset(testAssetName, $"DebugLevelTests_BuildWithExplicitValue_{configuration}", "App"); + BuildPublishProject(projectFile, configuration, extraArgs: $"-p:WasmDebugLevel={debugLevel}"); + + string result = await RunBuiltBrowserApp(configuration, projectFile, testScenario: "DebugLevelTest"); + AssertDebugLevel(result, debugLevel); + } + + [Theory] + [InlineData("Debug")] + [InlineData("Release")] + public async Task PublishWithDefaultLevel(string configuration) + { + string testAssetName = "WasmBasicTestApp"; + string projectFile = $"{testAssetName}.csproj"; + CopyTestAsset(testAssetName, $"DebugLevelTests_PublishWithDefaultLevel_{configuration}", "App"); + BuildPublishProject(projectFile, configuration, isPublish: true); + + string result = await RunPublishedBrowserApp(configuration, testScenario: "DebugLevelTest"); + AssertDebugLevel(result, 0); + } + + [Theory] + [InlineData("Debug", 1)] + [InlineData("Release", 1)] + [InlineData("Debug", -1)] + [InlineData("Release", -1)] + public async Task PublishWithExplicitValue(string configuration, int debugLevel) + { + string testAssetName = "WasmBasicTestApp"; + string projectFile = $"{testAssetName}.csproj"; + CopyTestAsset(testAssetName, $"DebugLevelTests_PublishWithExplicitValue_{configuration}", "App"); + BuildPublishProject(projectFile, configuration, isPublish: true, extraArgs: $"-p:WasmDebugLevel={debugLevel}"); + + string result = await RunBuiltBrowserApp(configuration, projectFile, testScenario: "DebugLevelTest"); + AssertDebugLevel(result, debugLevel); + } + + + [Theory] + [InlineData("Debug")] + [InlineData("Release")] + public async Task PublishWithDefaultLevelAndPdbs(string configuration) + { + string testAssetName = "WasmBasicTestApp"; + string projectFile = $"{testAssetName}.csproj"; + CopyTestAsset(testAssetName, $"DebugLevelTests_PublishWithDefaultLevelAndPdbs_{configuration}", "App"); + BuildPublishProject(projectFile, configuration, isPublish: true, extraArgs: $"-p:CopyOutputSymbolsToPublishDirectory=true"); + + var result = await RunPublishedBrowserApp(configuration, testScenario: "DebugLevelTest"); + AssertDebugLevel(result, -1); + } +} diff --git a/src/mono/wasm/Wasm.Build.Tests/HybridGlobalizationTests.cs b/src/mono/wasm/Wasm.Build.Tests/HybridGlobalizationTests.cs index 66cee78c5de833..8d1a861dc213cc 100644 --- a/src/mono/wasm/Wasm.Build.Tests/HybridGlobalizationTests.cs +++ b/src/mono/wasm/Wasm.Build.Tests/HybridGlobalizationTests.cs @@ -44,7 +44,7 @@ private void TestHybridGlobalizationTests(BuildArgs buildArgs, RunHost host, str buildArgs = ExpandBuildArgs(buildArgs, extraProperties); if (dotnetWasmFromRuntimePack == null) - dotnetWasmFromRuntimePack = !(buildArgs.AOT || buildArgs.Config == "Release"); + dotnetWasmFromRuntimePack = IsDotnetWasmFromRuntimePack(buildArgs); string programText = File.ReadAllText(Path.Combine(BuildEnvironment.TestAssetsPath, "Wasm.Buid.Tests.Programs", "HybridGlobalization.cs")); diff --git a/src/mono/wasm/Wasm.Build.Tests/IcuShardingTests.cs b/src/mono/wasm/Wasm.Build.Tests/IcuShardingTests.cs index c4fdf83966bb84..02abd96db46c21 100644 --- a/src/mono/wasm/Wasm.Build.Tests/IcuShardingTests.cs +++ b/src/mono/wasm/Wasm.Build.Tests/IcuShardingTests.cs @@ -35,7 +35,6 @@ public static IEnumerable IcuExpectedAndMissingAutomaticShardTestData( { "ja-JP", GetCjkTestedLocales(SundayNames.Japanese) }, { "sk-SK", GetNocjkTestedLocales(SundayNames.Slovak) } }; - // "wasmconsole": https://github.com/dotnet/runtime/issues/82593 return from aot in boolOptions from locale in locales select new object[] { config, "wasmbrowser", aot, locale.Key, locale.Value }; diff --git a/src/mono/wasm/Wasm.Build.Tests/IcuShardingTests2.cs b/src/mono/wasm/Wasm.Build.Tests/IcuShardingTests2.cs index 38acd3f8485667..8f7e8ad459332a 100644 --- a/src/mono/wasm/Wasm.Build.Tests/IcuShardingTests2.cs +++ b/src/mono/wasm/Wasm.Build.Tests/IcuShardingTests2.cs @@ -31,11 +31,10 @@ public static IEnumerable IcuExpectedAndMissingShardFromRuntimePackTes { "icudt_no_CJK.dat", GetNocjkTestedLocales() } }; return - // "wasmconsole": https://github.com/dotnet/runtime/issues/82593 - // from templateType in templateTypes + from templateType in templateTypes from aot in boolOptions from locale in locales - select new object[] { config, "wasmbrowser", aot, locale.Key, locale.Value }; + select new object[] { config, templateType, aot, locale.Key, locale.Value }; } [Theory] diff --git a/src/mono/wasm/Wasm.Build.Tests/IcuTests.cs b/src/mono/wasm/Wasm.Build.Tests/IcuTests.cs index 6c0e2c5ae9c55b..d3f808c87a5143 100644 --- a/src/mono/wasm/Wasm.Build.Tests/IcuTests.cs +++ b/src/mono/wasm/Wasm.Build.Tests/IcuTests.cs @@ -65,8 +65,6 @@ await BuildAndRunIcuTest( globalizationMode: invariant ? GlobalizationMode.Invariant : fullIcu ? GlobalizationMode.FullIcu : GlobalizationMode.Sharded, extraProperties: // https://github.com/dotnet/runtime/issues/94133: "wasmbrowser" should use WasmIncludeFullIcuData, not BlazorWebAssemblyLoadAllGlobalizationData - templateType == "wasmconsole" ? - $"{invariant}{fullIcu}{aot}" : $"{invariant}{fullIcu}{aot}"); [Theory] @@ -90,35 +88,25 @@ public async Task FullIcuFromRuntimePackWithCustomIcu(string config, string temp [MemberData(nameof(IncorrectIcuTestData), parameters: new object[] { "Release" })] public void NonExistingCustomFileAssertError(string config, string templateType, string customIcu, bool isFilenameFormCorrect) { - bool isBrowser = templateType == "wasmbrowser"; - string customIcuProperty = isBrowser ? "BlazorIcuDataFileName" : "WasmIcuDataFileName"; + string customIcuProperty = "BlazorIcuDataFileName"; string extraProperties = $"<{customIcuProperty}>{customIcu}"; (BuildArgs buildArgs, string projectFile) = CreateIcuProject( config, templateType, aot: false, "Array.Empty()", extraProperties); string output = BuildIcuTest( buildArgs, - isBrowser, GlobalizationMode.Custom, customIcu, expectSuccess: false, assertAppBundle: false); - if (isBrowser) + if (isFilenameFormCorrect) { - if (isFilenameFormCorrect) - { - Assert.Contains($"Could not find $({customIcuProperty})={customIcu}, or when used as a path relative to the runtime pack", output); - } - else - { - Assert.Contains($"File name in $({customIcuProperty}) has to start with 'icudt'.", output); - } + Assert.Contains($"Could not find $({customIcuProperty})={customIcu}, or when used as a path relative to the runtime pack", output); } else { - // https://github.com/dotnet/runtime/issues/102743: console apps should also require "icudt" at the beginning, unify it - Assert.Contains($"File in location $({customIcuProperty})={customIcu} cannot be found neither when used as absolute path nor a relative runtime pack path.", output); + Assert.Contains($"File name in $({customIcuProperty}) has to start with 'icudt'.", output); } } } diff --git a/src/mono/wasm/Wasm.Build.Tests/IcuTestsBase.cs b/src/mono/wasm/Wasm.Build.Tests/IcuTestsBase.cs index 3aefcdd0762f63..25a03ad781dcec 100644 --- a/src/mono/wasm/Wasm.Build.Tests/IcuTestsBase.cs +++ b/src/mono/wasm/Wasm.Build.Tests/IcuTestsBase.cs @@ -18,7 +18,7 @@ public IcuTestsBase(ITestOutputHelper output, SharedBuildPerTestClassFixture bui : base(output, buildContext) { } private const string _fallbackSundayNameEnUS = "Sunday"; - protected static string[] templateTypes = { "wasmconsole", "wasmbrowser" }; + protected static string[] templateTypes = { "wasmbrowser" }; protected static bool[] boolOptions = { false, true }; protected record SundayNames @@ -108,8 +108,7 @@ public record Locale(string Code, string? SundayName); protected async Task TestIcuShards(string config, string templateType, bool aot, string shardName, string testedLocales, GlobalizationMode globalizationMode, bool onlyPredefinedCultures=false) { - bool isBrowser = templateType == "wasmbrowser"; - string icuProperty = isBrowser ? "BlazorIcuDataFileName" : "WasmIcuDataFileName"; // https://github.com/dotnet/runtime/issues/94133 + string icuProperty = "BlazorIcuDataFileName"; // https://github.com/dotnet/runtime/issues/94133 // by default, we remove resource strings from an app. ICU tests are checking exception messages contents -> resource string keys are not enough string extraProperties = $"<{icuProperty}>{shardName}false{aot}"; if (onlyPredefinedCultures) @@ -138,39 +137,35 @@ protected async Task TestIcuShards(string config, string templateType, bool aot, File.WriteAllText(programPath, programText); _testOutput.WriteLine($"----- Program: -----{Environment.NewLine}{programText}{Environment.NewLine}-------"); - bool isBrowser = templateType == "wasmbrowser"; - string mainPath = isBrowser ? Path.Combine("wwwroot", "main.js") : "main.mjs"; - var replacements = isBrowser ? new Dictionary { + string mainPath = Path.Combine("wwwroot", "main.js"); + var replacements = new Dictionary { { "runMain", "runMainAndExit" }, { ".create()", ".withConsoleForwarding().withElementOnExit().withExitCodeLogging().create()" } - } : new Dictionary { - { ".create()", ".withConsoleForwarding().withElementOnExit().withExitCodeLogging().create()" } }; - UpdateProjectFile(mainPath, replacements); + UpdateFile(mainPath, replacements); RemoveContentsFromProjectFile(mainPath, ".create();", "await runMainAndExit();"); return (buildArgs, projectFile); } protected string BuildIcuTest( BuildArgs buildArgs, - bool isBrowser, GlobalizationMode globalizationMode, string icuFileName = "", bool expectSuccess = true, bool assertAppBundle = true) { - bool dotnetWasmFromRuntimePack = !(buildArgs.AOT || buildArgs.Config == "Release"); + bool dotnetWasmFromRuntimePack = IsDotnetWasmFromRuntimePack(buildArgs); (string _, string buildOutput) = BuildTemplateProject(buildArgs, id: buildArgs.Id, new BuildProjectOptions( DotnetWasmFromRuntimePack: dotnetWasmFromRuntimePack, CreateProject: false, HasV8Script: false, - MainJS: isBrowser ? "main.js" : "main.mjs", + MainJS: "main.js", Publish: true, TargetFramework: BuildTestBase.DefaultTargetFramework, UseCache: false, - IsBrowserProject: isBrowser, + IsBrowserProject: true, GlobalizationMode: globalizationMode, CustomIcuFile: icuFileName, ExpectSuccess: expectSuccess, @@ -192,13 +187,10 @@ protected async Task BuildAndRunIcuTest( { try { - bool isBrowser = templateType == "wasmbrowser"; (BuildArgs buildArgs, string projectFile) = CreateIcuProject( config, templateType, aot, testedLocales, extraProperties, onlyPredefinedCultures); - string buildOutput = BuildIcuTest(buildArgs, isBrowser, globalizationMode, icuFileName); - string runOutput = isBrowser ? - await RunBrowser(buildArgs.Config, projectFile, language) : - RunConsole(buildArgs, language: language); + string buildOutput = BuildIcuTest(buildArgs, globalizationMode, icuFileName); + string runOutput = await RunBuiltBrowserApp(buildArgs.Config, projectFile, language); return $"{buildOutput}\n{runOutput}"; } catch(Exception ex) diff --git a/src/mono/wasm/Wasm.Build.Tests/InvariantGlobalizationTests.cs b/src/mono/wasm/Wasm.Build.Tests/InvariantGlobalizationTests.cs index 816f088666731c..212d2205987dd9 100644 --- a/src/mono/wasm/Wasm.Build.Tests/InvariantGlobalizationTests.cs +++ b/src/mono/wasm/Wasm.Build.Tests/InvariantGlobalizationTests.cs @@ -52,7 +52,7 @@ private void TestInvariantGlobalization(BuildArgs buildArgs, bool? invariantGlob buildArgs = ExpandBuildArgs(buildArgs, extraProperties); if (dotnetWasmFromRuntimePack == null) - dotnetWasmFromRuntimePack = !(buildArgs.AOT || buildArgs.Config == "Release"); + dotnetWasmFromRuntimePack = IsDotnetWasmFromRuntimePack(buildArgs); BuildProject(buildArgs, id: id, diff --git a/src/mono/wasm/Wasm.Build.Tests/InvariantTimezoneTests.cs b/src/mono/wasm/Wasm.Build.Tests/InvariantTimezoneTests.cs index 49a6569ebda058..75a1af9cd3caff 100644 --- a/src/mono/wasm/Wasm.Build.Tests/InvariantTimezoneTests.cs +++ b/src/mono/wasm/Wasm.Build.Tests/InvariantTimezoneTests.cs @@ -50,7 +50,7 @@ private void TestInvariantTimezone(BuildArgs buildArgs, bool? invariantTimezone, buildArgs = ExpandBuildArgs(buildArgs, extraProperties); if (dotnetWasmFromRuntimePack == null) - dotnetWasmFromRuntimePack = !(buildArgs.AOT || buildArgs.Config == "Release"); + dotnetWasmFromRuntimePack = IsDotnetWasmFromRuntimePack(buildArgs); BuildProject(buildArgs, id: id, diff --git a/src/mono/wasm/Wasm.Build.Tests/MainWithArgsTests.cs b/src/mono/wasm/Wasm.Build.Tests/MainWithArgsTests.cs index fea9d10c3d16f3..5fb7887e962cfa 100644 --- a/src/mono/wasm/Wasm.Build.Tests/MainWithArgsTests.cs +++ b/src/mono/wasm/Wasm.Build.Tests/MainWithArgsTests.cs @@ -71,7 +71,7 @@ void TestMainWithArgs(string projectNamePrefix, buildArgs = buildArgs with { ProjectName = projectName, ProjectFileContents = programText }; buildArgs = ExpandBuildArgs(buildArgs); if (dotnetWasmFromRuntimePack == null) - dotnetWasmFromRuntimePack = !(buildArgs.AOT || buildArgs.Config == "Release"); + dotnetWasmFromRuntimePack = IsDotnetWasmFromRuntimePack(buildArgs); _testOutput.WriteLine ($"-- args: {buildArgs}, name: {projectName}"); diff --git a/src/mono/wasm/Wasm.Build.Tests/ProjectProviderBase.cs b/src/mono/wasm/Wasm.Build.Tests/ProjectProviderBase.cs index 6f440be4481441..417bf4b8d2a51d 100644 --- a/src/mono/wasm/Wasm.Build.Tests/ProjectProviderBase.cs +++ b/src/mono/wasm/Wasm.Build.Tests/ProjectProviderBase.cs @@ -36,7 +36,7 @@ public abstract class ProjectProviderBase(ITestOutputHelper _testOutput, string? public string? ProjectDir { get; set; } = _projectDir; protected ITestOutputHelper _testOutput = new TestOutputWrapper(_testOutput); protected BuildEnvironment _buildEnv = BuildTestBase.s_buildEnv; - public string BundleDirName { get; set; } = "wwwroot"; + protected abstract string BundleDirName { get; } public bool IsFingerprintingSupported { get; protected set; } @@ -414,7 +414,6 @@ public void AssertIcuAssets(AssertBundleOptionsBase assertOptions, BootJsonData public BootJsonData AssertBootJson(AssertBundleOptionsBase options) { EnsureProjectDirIsSet(); - // string binFrameworkDir = FindBinFrameworkDir(options.Config, options.IsPublish, options.TargetFramework); string binFrameworkDir = options.BinFrameworkDir; string bootJsonPath = Path.Combine(binFrameworkDir, options.BootJsonFileName); Assert.True(File.Exists(bootJsonPath), $"Expected to find {bootJsonPath}"); @@ -520,14 +519,9 @@ private void AssertFileNames(IEnumerable expected, IEnumerable a Assert.Equal(expected, actualFileNames); } - public virtual string FindBinFrameworkDir(string config, bool forPublish, string framework, string? bundleDirName = null, string? projectDir = null) + public virtual string FindBinFrameworkDir(string config, bool forPublish, string framework, string? projectDir = null) { - EnsureProjectDirIsSet(); - string basePath = Path.Combine(projectDir ?? ProjectDir!, "bin", config, framework); - if (forPublish) - basePath = FindSubDirIgnoringCase(basePath, "publish"); - - return Path.Combine(basePath, bundleDirName ?? this.BundleDirName, "_framework"); + throw new NotImplementedException(); } [MemberNotNull(nameof(ProjectDir))] diff --git a/src/mono/wasm/Wasm.Build.Tests/Templates/NativeBuildTests.cs b/src/mono/wasm/Wasm.Build.Tests/Templates/NativeBuildTests.cs index ff111d60207aa2..e76e1112e6b638 100644 --- a/src/mono/wasm/Wasm.Build.Tests/Templates/NativeBuildTests.cs +++ b/src/mono/wasm/Wasm.Build.Tests/Templates/NativeBuildTests.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.IO; +using System.Threading.Tasks; using Wasm.Build.Tests; using Xunit; using Xunit.Abstractions; @@ -10,7 +11,7 @@ namespace Wasm.Build.Templates.Tests { - public class NativeBuildTests : WasmTemplateTestBase + public class NativeBuildTests : WasmTemplateTestsBase { public NativeBuildTests(ITestOutputHelper output, SharedBuildPerTestClassFixture buildContext) : base(output, buildContext) @@ -65,37 +66,40 @@ public void BuildWithUndefinedNativeSymbol(bool allowUndefined) [Theory] [InlineData("Debug")] [InlineData("Release")] - public void ProjectWithDllImportsRequiringMarshalIlGen_ArrayTypeParameter(string config) + public async Task ProjectWithDllImportsRequiringMarshalIlGen_ArrayTypeParameter(string config) { string id = $"dllimport_incompatible_{GetRandomId()}"; - string projectPath = CreateWasmTemplateProject(id, template: "wasmconsole"); + string projectFile = CreateWasmTemplateProject(id, template: "wasmbrowser"); + string projectName = Path.GetFileNameWithoutExtension(projectFile); string nativeSourceFilename = "incompatible_type.c"; string nativeCode = "void call_needing_marhsal_ilgen(void *x) {}"; File.WriteAllText(path: Path.Combine(_projectDir!, nativeSourceFilename), nativeCode); AddItemsPropertiesToProject( - projectPath, + projectFile, extraItems: "" ); + UpdateBrowserMainJs(); File.Copy(Path.Combine(BuildEnvironment.TestAssetsPath, "marshal_ilgen_test.cs"), Path.Combine(_projectDir!, "Program.cs"), overwrite: true); - using DotNetCommand cmd = new DotNetCommand(s_buildEnv, _testOutput); - CommandResult result = cmd.WithWorkingDirectory(_projectDir!) - .WithEnvironmentVariable("NUGET_PACKAGES", _nugetPackagesDir) - .ExecuteWithCapturedOutput("build", $"-c {config} -bl"); - - Assert.True(result.ExitCode == 0, "Expected build to succeed"); - - using RunCommand runCmd = new RunCommand(s_buildEnv, _testOutput); - CommandResult res = runCmd.WithWorkingDirectory(_projectDir!) - .ExecuteWithCapturedOutput($"run --no-silent --no-build -c {config}") - .EnsureSuccessful(); - Assert.Contains("Hello, Console!", res.Output); - Assert.Contains("Hello, World! Greetings from node version", res.Output); + var buildArgs = new BuildArgs(projectName, config, false, id, null); + buildArgs = ExpandBuildArgs(buildArgs); + BuildTemplateProject(buildArgs, id: id, new BuildProjectOptions( + AssertAppBundle: false, + CreateProject: false, + HasV8Script: false, + MainJS: "main.mjs", + Publish: false, + TargetFramework: DefaultTargetFramework, + IsBrowserProject: true) + ); + string runOutput = await RunBuiltBrowserApp(config, projectFile); + + Assert.Contains("call_needing_marhsal_ilgen got called", runOutput); } } } diff --git a/src/mono/wasm/Wasm.Build.Tests/Templates/WasmTemplateTests.cs b/src/mono/wasm/Wasm.Build.Tests/Templates/WasmTemplateTests.cs index f6121667a0fefa..89107e11d1868e 100644 --- a/src/mono/wasm/Wasm.Build.Tests/Templates/WasmTemplateTests.cs +++ b/src/mono/wasm/Wasm.Build.Tests/Templates/WasmTemplateTests.cs @@ -21,27 +21,21 @@ public WasmTemplateTests(ITestOutputHelper output, SharedBuildPerTestClassFixtur : base(output, buildContext) { } - - private static string s_consoleProgramUpdateText = """ - Console.WriteLine("Hello, Console!"); - - for (int i = 0; i < args.Length; i ++) - Console.WriteLine ($"args[{i}] = {args[i]}"); - """; - private Dictionary consoleProgramReplacements = new Dictionary - { - { "Console.WriteLine(\"Hello, Console!\");", s_consoleProgramUpdateText }, - { "return 0;", "return 42;" } - }; - private Dictionary browserProgramReplacements = new Dictionary - { - { "while(true)", $"int i = 0;{Environment.NewLine}while(i++ < 10)" }, - { "partial class StopwatchSample", $"return 42;{Environment.NewLine}partial class StopwatchSample" } - }; - private Dictionary consoleMainJSReplacements = new Dictionary - { - { ".create()", ".withConsoleForwarding().create()" } - }; + + private BuildProjectOptions _basePublishProjectOptions = new BuildProjectOptions( + DotnetWasmFromRuntimePack: false, + CreateProject: false, + HasV8Script: false, + MainJS: "main.js", + Publish: true + ); + private BuildProjectOptions _baseBuildProjectOptions = new BuildProjectOptions( + DotnetWasmFromRuntimePack: true, + CreateProject: false, + HasV8Script: false, + MainJS: "main.js", + Publish: false + ); [Theory, TestCategory("no-fingerprinting")] [InlineData("Debug")] @@ -52,8 +46,8 @@ public void BrowserBuildThenPublish(string config) string projectFile = CreateWasmTemplateProject(id, "wasmbrowser"); string projectName = Path.GetFileNameWithoutExtension(projectFile); - UpdateProjectFile("Program.cs", browserProgramReplacements); - UpdateBrowserMainJs(DefaultTargetFramework); + UpdateBrowserProgramFile(); + UpdateBrowserMainJs(); var buildArgs = new BuildArgs(projectName, config, false, id, null); @@ -70,17 +64,7 @@ public void BrowserBuildThenPublish(string config) ); buildArgs = ExpandBuildArgs(buildArgs); - - BuildTemplateProject(buildArgs, - id: id, - new BuildProjectOptions( - DotnetWasmFromRuntimePack: true, - CreateProject: false, - HasV8Script: false, - MainJS: "main.js", - Publish: false, - TargetFramework: BuildTestBase.DefaultTargetFramework - )); + BuildTemplateProject(buildArgs, id: id, _baseBuildProjectOptions); if (!_buildContext.TryGetBuildFor(buildArgs, out BuildProduct? product)) throw new XunitException($"Test bug: could not get the build product in the cache"); @@ -92,138 +76,27 @@ public void BrowserBuildThenPublish(string config) bool expectRelinking = config == "Release"; BuildTemplateProject(buildArgs, id: id, - new BuildProjectOptions( - DotnetWasmFromRuntimePack: !expectRelinking, - CreateProject: false, - HasV8Script: false, - MainJS: "main.js", - Publish: true, - TargetFramework: BuildTestBase.DefaultTargetFramework, - UseCache: false)); + _basePublishProjectOptions with + { + UseCache = false, + DotnetWasmFromRuntimePack = !expectRelinking, + } + ); } - [Theory] - [InlineData("Debug")] - [InlineData("Release")] - public void ConsoleBuildThenPublish(string config) + public static TheoryData TestDataForAppBundleDir() { - string id = $"{config}_{GetRandomId()}"; - string projectFile = CreateWasmTemplateProject(id, "wasmconsole"); - string projectName = Path.GetFileNameWithoutExtension(projectFile); - - UpdateProjectFile("main.mjs", consoleMainJSReplacements); - - var buildArgs = new BuildArgs(projectName, config, false, id, null); - buildArgs = ExpandBuildArgs(buildArgs); - - BuildTemplateProject(buildArgs, - id: id, - new BuildProjectOptions( - DotnetWasmFromRuntimePack: true, - CreateProject: false, - HasV8Script: false, - MainJS: "main.mjs", - Publish: false, - TargetFramework: BuildTestBase.DefaultTargetFramework, - IsBrowserProject: false - )); - - using RunCommand cmd = new RunCommand(s_buildEnv, _testOutput); - CommandResult res = cmd.WithWorkingDirectory(_projectDir!) - .ExecuteWithCapturedOutput($"run --no-silent --no-build -c {config}") - .EnsureSuccessful(); - Assert.Contains("Hello, Console!", res.Output); + var data = new TheoryData(); + AddTestData(runOutsideProjectDirectory: false); + AddTestData(runOutsideProjectDirectory: true); - if (!_buildContext.TryGetBuildFor(buildArgs, out BuildProduct? product)) - throw new XunitException($"Test bug: could not get the build product in the cache"); - - File.Move(product!.LogFile, Path.ChangeExtension(product.LogFile!, ".first.binlog")); - - _testOutput.WriteLine($"{Environment.NewLine}Publishing with no changes ..{Environment.NewLine}"); - - bool expectRelinking = config == "Release"; - BuildTemplateProject(buildArgs, - id: id, - new BuildProjectOptions( - DotnetWasmFromRuntimePack: !expectRelinking, - CreateProject: false, - HasV8Script: false, - MainJS: "main.mjs", - Publish: true, - TargetFramework: BuildTestBase.DefaultTargetFramework, - UseCache: false, - IsBrowserProject: false)); - } - - [Theory] - [InlineData("Debug", false)] - [InlineData("Debug", true)] - [InlineData("Release", false)] - [InlineData("Release", true)] - public void ConsoleBuildAndRunDefault(string config, bool relinking) - => ConsoleBuildAndRun(config, relinking, string.Empty, DefaultTargetFramework, addFrameworkArg: true); - - [Theory] - // [ActiveIssue("https://github.com/dotnet/runtime/issues/79313")] - // [InlineData("Debug", "-f net7.0", "net7.0")] - //[InlineData("Debug", "-f net8.0", "net8.0")] - [InlineData("Debug", "-f net9.0", "net9.0")] - public void ConsoleBuildAndRunForSpecificTFM(string config, string extraNewArgs, string expectedTFM) - => ConsoleBuildAndRun(config, false, extraNewArgs, expectedTFM, addFrameworkArg: extraNewArgs?.Length == 0); - - private void ConsoleBuildAndRun(string config, bool relinking, string extraNewArgs, string expectedTFM, bool addFrameworkArg) - { - string id = $"{config}_{GetRandomId()}"; - string projectFile = CreateWasmTemplateProject(id, "wasmconsole", extraNewArgs, addFrameworkArg: addFrameworkArg); - string projectName = Path.GetFileNameWithoutExtension(projectFile); - - UpdateProjectFile("Program.cs", consoleProgramReplacements); - UpdateProjectFile("main.mjs", consoleMainJSReplacements); - if (relinking) - AddItemsPropertiesToProject(projectFile, "true"); - - var buildArgs = new BuildArgs(projectName, config, false, id, null); - buildArgs = ExpandBuildArgs(buildArgs); - - BuildTemplateProject(buildArgs, - id: id, - new BuildProjectOptions( - DotnetWasmFromRuntimePack: !relinking, - CreateProject: false, - HasV8Script: false, - MainJS: "main.mjs", - Publish: false, - TargetFramework: expectedTFM, - IsBrowserProject: false - )); - - using RunCommand cmd = new RunCommand(s_buildEnv, _testOutput); - CommandResult res = cmd.WithWorkingDirectory(_projectDir!) - .ExecuteWithCapturedOutput($"run --no-silent --no-build -c {config} x y z") - .EnsureExitCode(42); - - Assert.Contains("args[0] = x", res.Output); - Assert.Contains("args[1] = y", res.Output); - Assert.Contains("args[2] = z", res.Output); - } - - public static TheoryData TestDataForAppBundleDir() - { - var data = new TheoryData(); - 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) + void AddTestData(bool runOutsideProjectDirectory) { // FIXME: Disabled for `main` right now, till 7.0 gets the fix - data.Add(runOutsideProjectDirectory, forConsole, string.Empty); - - data.Add(runOutsideProjectDirectory, forConsole, + data.Add(runOutsideProjectDirectory, string.Empty); + data.Add(runOutsideProjectDirectory, $"{Path.Combine(BuildEnvironment.TmpPath, Path.GetRandomFileName())}"); - data.Add(runOutsideProjectDirectory, forConsole, + data.Add(runOutsideProjectDirectory, $"{Path.Combine(BuildEnvironment.TmpPath, Path.GetRandomFileName())}"); } @@ -233,18 +106,16 @@ void AddTestData(bool forConsole, bool runOutsideProjectDirectory) [Theory, TestCategory("no-fingerprinting")] [MemberData(nameof(TestDataForAppBundleDir))] [ActiveIssue("https://github.com/dotnet/runtime/issues/108107")] - public async Task RunWithDifferentAppBundleLocations(bool forConsole, bool runOutsideProjectDirectory, string extraProperties) - => await (forConsole - ? ConsoleRunWithAndThenWithoutBuildAsync("Release", extraProperties, runOutsideProjectDirectory) - : BrowserRunTwiceWithAndThenWithoutBuildAsync("Release", extraProperties, runOutsideProjectDirectory)); + public async Task RunWithDifferentAppBundleLocations(bool runOutsideProjectDirectory, string extraProperties) + => await BrowserRunTwiceWithAndThenWithoutBuildAsync("Release", extraProperties, runOutsideProjectDirectory); private async Task BrowserRunTwiceWithAndThenWithoutBuildAsync(string config, string extraProperties = "", bool runOutsideProjectDirectory = false) { string id = $"browser_{config}_{GetRandomId()}"; string projectFile = CreateWasmTemplateProject(id, "wasmbrowser"); - UpdateProjectFile("Program.cs", browserProgramReplacements); - UpdateBrowserMainJs(DefaultTargetFramework); + UpdateBrowserProgramFile(); + UpdateBrowserMainJs(); if (!string.IsNullOrEmpty(extraProperties)) AddItemsPropertiesToProject(projectFile, extraProperties: extraProperties); @@ -272,121 +143,6 @@ private async Task BrowserRunTwiceWithAndThenWithoutBuildAsync(string config, st } } - private Task ConsoleRunWithAndThenWithoutBuildAsync(string config, string extraProperties = "", bool runOutsideProjectDirectory = false) - { - string id = $"console_{config}_{GetRandomId()}"; - string projectFile = CreateWasmTemplateProject(id, "wasmconsole"); - - UpdateProjectFile("Program.cs", consoleProgramReplacements); - UpdateProjectFile("main.mjs", consoleMainJSReplacements); - - if (!string.IsNullOrEmpty(extraProperties)) - AddItemsPropertiesToProject(projectFile, extraProperties: extraProperties); - - string workingDir = runOutsideProjectDirectory ? BuildEnvironment.TmpPath : _projectDir!; - - { - string runArgs = $"run --no-silent -c {config} --project \"{projectFile}\""; - runArgs += " x y z"; - using var cmd = new RunCommand(s_buildEnv, _testOutput, label: id) - .WithWorkingDirectory(workingDir) - .WithEnvironmentVariables(s_buildEnv.EnvVars); - CommandResult 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 --no-silent -c {config} --project \"{projectFile}\" --no-build"; - runArgs += " x y z"; - using var cmd = new RunCommand(s_buildEnv, _testOutput, label: id) - .WithWorkingDirectory(workingDir); - CommandResult 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 TestDataForConsolePublishAndRun() - { - var data = new TheoryData(); - data.Add("Debug", false, false); - data.Add("Debug", false, true); - data.Add("Release", false, false); // Release relinks by default - data.Add("Release", true, false); - - return data; - } - - [Theory] - [MemberData(nameof(TestDataForConsolePublishAndRun))] - public void ConsolePublishAndRun(string config, bool aot, bool relinking) - { - string id = $"{config}_{GetRandomId()}"; - string projectFile = CreateWasmTemplateProject(id, "wasmconsole"); - string projectName = Path.GetFileNameWithoutExtension(projectFile); - - UpdateProjectFile("Program.cs", consoleProgramReplacements); - UpdateProjectFile("main.mjs", consoleMainJSReplacements); - - if (aot) - { - // FIXME: pass envvars via the environment, once that is supported - UpdateMainJsEnvironmentVariables(("MONO_LOG_MASK", "aot"), ("MONO_LOG_LEVEL", "debug")); - AddItemsPropertiesToProject(projectFile, "true"); - } - else if (relinking) - { - AddItemsPropertiesToProject(projectFile, "true"); - } - - var buildArgs = new BuildArgs(projectName, config, aot, id, null); - buildArgs = ExpandBuildArgs(buildArgs); - - bool expectRelinking = config == "Release" || aot || relinking; - BuildTemplateProject(buildArgs, - id: id, - new BuildProjectOptions( - DotnetWasmFromRuntimePack: !expectRelinking, - CreateProject: false, - HasV8Script: false, - MainJS: "main.mjs", - Publish: true, - TargetFramework: BuildTestBase.DefaultTargetFramework, - UseCache: false, - IsBrowserProject: false)); - - using (RunCommand cmd = new RunCommand(s_buildEnv, _testOutput, label: id)) - { - cmd.WithWorkingDirectory(_projectDir!) - .ExecuteWithCapturedOutput("--info") - .EnsureExitCode(0); - } - - string runArgs = $"run --no-silent --no-build -c {config} -v diag"; - runArgs += " x y z"; - using (RunCommand cmd = new RunCommand(s_buildEnv, _testOutput, label: id)) - { - CommandResult res = cmd.WithWorkingDirectory(_projectDir!) - .ExecuteWithCapturedOutput(runArgs) - .EnsureExitCode(42); - if (aot) - Assert.Contains($"AOT: image '{Path.GetFileNameWithoutExtension(projectFile)}' found", res.Output); - Assert.Contains("args[0] = x", res.Output); - Assert.Contains("args[1] = y", res.Output); - Assert.Contains("args[2] = z", res.Output); - } - } - public static IEnumerable BrowserBuildAndRunTestData() { yield return new object?[] { "", BuildTestBase.DefaultTargetFramework, DefaultRuntimeAssetsRelativePath }; @@ -402,29 +158,31 @@ public void ConsolePublishAndRun(string config, bool aot, bool relinking) [Theory] [MemberData(nameof(BrowserBuildAndRunTestData))] - public async Task BrowserBuildAndRun(string extraNewArgs, string targetFramework, string runtimeAssetsRelativePath) + public async Task BrowserBuildAndRun(string extraNewArgs, string targetFramework, string runtimeAssetsRelativePath) { string config = "Debug"; string id = $"browser_{config}_{GetRandomId()}"; - CreateWasmTemplateProject(id, "wasmbrowser", extraNewArgs, addFrameworkArg: extraNewArgs.Length == 0); + string projectFile = CreateWasmTemplateProject(id, "wasmbrowser", extraNewArgs, addFrameworkArg: extraNewArgs.Length == 0); + string projectName = Path.GetFileNameWithoutExtension(projectFile); + string extraProperties = runtimeAssetsRelativePath == DefaultRuntimeAssetsRelativePath ? + "" : + $"{runtimeAssetsRelativePath}"; + AddItemsPropertiesToProject(projectFile, extraProperties); if (targetFramework != "net8.0") - UpdateProjectFile("Program.cs", browserProgramReplacements); - + UpdateBrowserProgramFile(); UpdateBrowserMainJs(targetFramework, runtimeAssetsRelativePath); using ToolCommand cmd = new DotNetCommand(s_buildEnv, _testOutput) .WithWorkingDirectory(_projectDir!); cmd.Execute($"build -c {config} -bl:{Path.Combine(s_buildEnv.LogRootPath, $"{id}.binlog")} {(runtimeAssetsRelativePath != DefaultRuntimeAssetsRelativePath ? "-p:WasmRuntimeAssetsLocation=" + runtimeAssetsRelativePath : "")}") .EnsureSuccessful(); + var buildArgs = new BuildArgs(projectName, config, false, id, null); + buildArgs = ExpandBuildArgs(buildArgs); + BuildTemplateProject(buildArgs, id: id, _baseBuildProjectOptions); - using var runCommand = new RunCommand(s_buildEnv, _testOutput) - .WithWorkingDirectory(_projectDir!); - - await using var runner = new BrowserRunner(_testOutput); - var page = await runner.RunAsync(runCommand, $"run --no-silent -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)); + string runOutput = await RunBuiltBrowserApp(config, projectFile); + Assert.Contains("Hello, Browser!", runOutput); } [Theory] @@ -432,69 +190,67 @@ public async Task BrowserBuildAndRun(string extraNewArgs, string targetFramework [InlineData("Debug", /*appendRID*/ true, /*useArtifacts*/ true)] [InlineData("Debug", /*appendRID*/ false, /*useArtifacts*/ true)] [InlineData("Debug", /*appendRID*/ false, /*useArtifacts*/ false)] - public void BuildAndRunForDifferentOutputPaths(string config, bool appendRID, bool useArtifacts) + public async Task BuildAndRunForDifferentOutputPaths(string config, bool appendRID, bool useArtifacts) { string id = $"{config}_{GetRandomId()}"; - string projectFile = CreateWasmTemplateProject(id, "wasmconsole"); + string projectFile = CreateWasmTemplateProject(id, "wasmbrowser"); string projectName = Path.GetFileNameWithoutExtension(projectFile); + string projectDirectory = Path.GetDirectoryName(projectFile)!; - string extraPropertiesForDBP = ""; - if (appendRID) - extraPropertiesForDBP += "true"; - if (useArtifacts) - extraPropertiesForDBP += "true."; + UpdateBrowserProgramFile(); + UpdateBrowserMainJs(); - string projectDirectory = Path.GetDirectoryName(projectFile)!; - if (!string.IsNullOrEmpty(extraPropertiesForDBP)) - AddItemsPropertiesToProject(Path.Combine(projectDirectory, "Directory.Build.props"), - extraPropertiesForDBP); - - var buildOptions = new BuildProjectOptions( - DotnetWasmFromRuntimePack: true, - CreateProject: false, - HasV8Script: false, - MainJS: "main.mjs", - Publish: false, - TargetFramework: DefaultTargetFramework, - IsBrowserProject: false); + string extraPropertiesForDBP = string.Empty; + string frameworkDir = FindBinFrameworkDir(config, forPublish: false); + + var buildOptions = _baseBuildProjectOptions with + { + BinFrameworkDir = frameworkDir + }; if (useArtifacts) { + extraPropertiesForDBP += "true."; buildOptions = buildOptions with { + // browser app does not allow appending RID BinFrameworkDir = Path.Combine( projectDirectory, "bin", id, - $"{config.ToLower()}_{BuildEnvironment.DefaultRuntimeIdentifier}", - "AppBundle", + config.ToLower(), + "wwwroot", "_framework") }; } + if (appendRID) + { + extraPropertiesForDBP += "true"; + } + // UseArtifactsOutput cannot be set in a project file, due to MSBuild ordering constraints. + string propsPath = Path.Combine(projectDirectory, "Directory.Build.props"); + AddItemsPropertiesToProject(propsPath, extraPropertiesForDBP); var buildArgs = new BuildArgs(projectName, config, false, id, null); buildArgs = ExpandBuildArgs(buildArgs); BuildTemplateProject(buildArgs, id: id, buildOptions); - CommandResult res = new RunCommand(s_buildEnv, _testOutput) - .WithWorkingDirectory(_projectDir!) - .ExecuteWithCapturedOutput($"run --no-silent --no-build -c {config} x y z") - .EnsureSuccessful(); + await RunBuiltBrowserApp(config, projectFile, extraArgs: "x y z"); } [Theory] [InlineData("", true)] // Default case [InlineData("false", false)] // the other case - public void Test_WasmStripILAfterAOT(string stripILAfterAOT, bool expectILStripping) + public async Task Test_WasmStripILAfterAOT(string stripILAfterAOT, bool expectILStripping) { string config = "Release"; string id = $"strip_{config}_{GetRandomId()}"; - string projectFile = CreateWasmTemplateProject(id, "wasmconsole"); + string projectFile = CreateWasmTemplateProject(id, "wasmbrowser"); string projectName = Path.GetFileNameWithoutExtension(projectFile); string projectDirectory = Path.GetDirectoryName(projectFile)!; bool aot = true; - UpdateProjectFile("Program.cs", consoleProgramReplacements); - UpdateProjectFile("main.mjs", consoleMainJSReplacements); + UpdateBrowserProgramFile(); + UpdateBrowserMainJs(); string extraProperties = "true"; if (!string.IsNullOrEmpty(stripILAfterAOT)) @@ -503,27 +259,16 @@ public void Test_WasmStripILAfterAOT(string stripILAfterAOT, bool expectILStripp var buildArgs = new BuildArgs(projectName, config, aot, id, null); buildArgs = ExpandBuildArgs(buildArgs); - BuildTemplateProject(buildArgs, id: id, - new BuildProjectOptions( - CreateProject: false, - HasV8Script: false, - MainJS: "main.mjs", - Publish: true, - TargetFramework: BuildTestBase.DefaultTargetFramework, - UseCache: false, - IsBrowserProject: false, - AssertAppBundle: false)); - - string runArgs = $"run --no-silent --no-build -c {config}"; - using ToolCommand cmd = new RunCommand(s_buildEnv, _testOutput, label: id) - .WithWorkingDirectory(_projectDir!); - CommandResult res = cmd.ExecuteWithCapturedOutput(runArgs) - .EnsureExitCode(42); - - string frameworkDir = Path.Combine(projectDirectory, "bin", config, BuildTestBase.DefaultTargetFramework, "browser-wasm", "AppBundle", "_framework"); - string objBuildDir = Path.Combine(projectDirectory, "obj", config, BuildTestBase.DefaultTargetFramework, "browser-wasm", "wasm", "for-publish"); + _basePublishProjectOptions with { + UseCache = false, + AssertAppBundle = false + }); + + await RunBuiltBrowserApp(config, projectFile); + string frameworkDir = FindBinFrameworkDir(config, forPublish: true); + string objBuildDir = Path.Combine(projectDirectory, "obj", config, BuildTestBase.DefaultTargetFramework, "wasm", "for-publish"); TestWasmStripILAfterAOTOutput(objBuildDir, frameworkDir, expectILStripping, _testOutput); } @@ -586,20 +331,24 @@ internal static void TestWasmStripILAfterAOTOutput(string objBuildDir, string fr public void PublishPdb(bool copyOutputSymbolsToPublishDirectory) { string config = "Release"; - string id = $"publishpdb_{copyOutputSymbolsToPublishDirectory.ToString().ToLower()}_{GetRandomId()}"; - CreateWasmTemplateProject(id, "wasmbrowser"); - - (CommandResult result, _) = BlazorPublish(new BlazorBuildOptions(id, config), $"-p:CopyOutputSymbolsToPublishDirectory={copyOutputSymbolsToPublishDirectory.ToString().ToLower()}"); - result.EnsureSuccessful(); + string shouldCopy = copyOutputSymbolsToPublishDirectory.ToString().ToLower(); + string id = $"publishpdb_{shouldCopy}_{GetRandomId()}"; + string projectFile = CreateWasmTemplateProject(id, "wasmbrowser"); + string projectName = Path.GetFileNameWithoutExtension(projectFile); + var buildArgs = new BuildArgs(projectName, config, false, id, null); + buildArgs = ExpandBuildArgs(buildArgs); + AddItemsPropertiesToProject(projectFile, + extraProperties: $"{shouldCopy}"); - string publishFrameworkPath = Path.GetFullPath(FindBlazorBinFrameworkDir(config, forPublish: true)); + BuildTemplateProject(buildArgs, buildArgs.Id, _basePublishProjectOptions); + string publishPath = FindBinFrameworkDir(config, forPublish: true); AssertFile(".pdb"); AssertFile(".pdb.gz"); AssertFile(".pdb.br"); void AssertFile(string suffix) { - var fileName = Directory.EnumerateFiles(publishFrameworkPath, $"*{suffix}").FirstOrDefault(f => Path.GetFileNameWithoutExtension(f).StartsWith(id)); + var fileName = Directory.EnumerateFiles(publishPath, $"*{suffix}").FirstOrDefault(f => Path.GetFileNameWithoutExtension(f).StartsWith(id)); Assert.True(copyOutputSymbolsToPublishDirectory == (fileName != null && File.Exists(fileName)), $"The {fileName} file {(copyOutputSymbolsToPublishDirectory ? "should" : "shouldn't")} exist in publish folder"); } } diff --git a/src/mono/wasm/Wasm.Build.Tests/Templates/WasmTemplateTestsBase.cs b/src/mono/wasm/Wasm.Build.Tests/Templates/WasmTemplateTestsBase.cs index 0354ae1951dab9..6b668222cc2f75 100644 --- a/src/mono/wasm/Wasm.Build.Tests/Templates/WasmTemplateTestsBase.cs +++ b/src/mono/wasm/Wasm.Build.Tests/Templates/WasmTemplateTestsBase.cs @@ -13,113 +13,199 @@ #nullable enable -namespace Wasm.Build.Tests +namespace Wasm.Build.Tests; + +public class WasmTemplateTestsBase : BuildTestBase { - public class WasmTemplateTestsBase : BlazorWasmTestBase + private readonly WasmSdkBasedProjectProvider _provider; + protected const string DefaultRuntimeAssetsRelativePath = "./_framework/"; + public WasmTemplateTestsBase(ITestOutputHelper output, SharedBuildPerTestClassFixture buildContext, ProjectProviderBase? provider = null) + : base(provider ?? new WasmSdkBasedProjectProvider(output, DefaultTargetFramework), output, buildContext) { - public WasmTemplateTestsBase(ITestOutputHelper output, SharedBuildPerTestClassFixture buildContext) - : base(output, buildContext) - { - } + _provider = GetProvider(); + } - private string StringReplaceWithAssert(string oldContent, string oldValue, string newValue) + private Dictionary browserProgramReplacements = new Dictionary { - string newContent = oldContent.Replace(oldValue, newValue); - if (oldValue != newValue && oldContent == newContent) - throw new XunitException($"Replacing '{oldValue}' with '{newValue}' did not change the content '{oldContent}'"); + { "while(true)", $"int i = 0;{Environment.NewLine}while(i++ < 10)" }, + { "partial class StopwatchSample", $"return 42;{Environment.NewLine}partial class StopwatchSample" } + }; - return newContent; - } + public string CreateWasmTemplateProject(string id, string template = "wasmbrowser", string extraArgs = "", bool runAnalyzers = true, bool addFrameworkArg = false, string? extraProperties = null) + { + InitPaths(id); + InitProjectDir(_projectDir, addNuGetSourceForLocalPackages: true); + + File.WriteAllText(Path.Combine(_projectDir, "Directory.Build.props"), ""); + File.WriteAllText(Path.Combine(_projectDir, "Directory.Build.targets"), + """ + + + + + + + + """); + if (UseWBTOverridePackTargets) + File.Copy(BuildEnvironment.WasmOverridePacksTargetsPath, Path.Combine(_projectDir, Path.GetFileName(BuildEnvironment.WasmOverridePacksTargetsPath)), overwrite: true); + + if (addFrameworkArg) + extraArgs += $" -f {DefaultTargetFramework}"; + using DotNetCommand cmd = new DotNetCommand(s_buildEnv, _testOutput, useDefaultArgs: false); + CommandResult result = cmd.WithWorkingDirectory(_projectDir!) + .ExecuteWithCapturedOutput($"new {template} {extraArgs}") + .EnsureSuccessful(); + + string projectfile = Path.Combine(_projectDir!, $"{id}.csproj"); + + if (extraProperties == null) + extraProperties = string.Empty; + + extraProperties += "true"; + if (runAnalyzers) + extraProperties += "true"; + + AddItemsPropertiesToProject(projectfile, extraProperties); + + return projectfile; + } + + public (string projectDir, string buildOutput) BuildTemplateProject( + BuildArgs buildArgs, + string id, + BuildProjectOptions buildProjectOptions, + params string[] extraArgs) + { + if (buildProjectOptions.ExtraBuildEnvironmentVariables is null) + buildProjectOptions = buildProjectOptions with { ExtraBuildEnvironmentVariables = new Dictionary() }; + + // TODO: reenable this when the SDK supports targetting net10.0 + //buildProjectOptions.ExtraBuildEnvironmentVariables["TreatPreviousAsCurrent"] = "false"; - protected void UpdateProjectFile(string pathRelativeToProjectDir, Dictionary replacements) + (CommandResult res, string logFilePath) = BuildProjectWithoutAssert(id, buildArgs.Config, buildProjectOptions, extraArgs); + if (buildProjectOptions.UseCache) + _buildContext.CacheBuild(buildArgs, new BuildProduct(_projectDir!, logFilePath, true, res.Output)); + + if (buildProjectOptions.AssertAppBundle) { - var path = Path.Combine(_projectDir!, pathRelativeToProjectDir); - string text = File.ReadAllText(path); - foreach (var replacement in replacements) + if (buildProjectOptions.IsBrowserProject) + { + _provider.AssertWasmSdkBundle(buildArgs, buildProjectOptions, res.Output); + } + else { - text = StringReplaceWithAssert(text, replacement.Key, replacement.Value); + _provider.AssertTestMainJsBundle(buildArgs, buildProjectOptions, res.Output); } - File.WriteAllText(path, text); } + return (_projectDir!, res.Output); + } + + private string StringReplaceWithAssert(string oldContent, string oldValue, string newValue) + { + string newContent = oldContent.Replace(oldValue, newValue); + if (oldValue != newValue && oldContent == newContent) + throw new XunitException($"Replacing '{oldValue}' with '{newValue}' did not change the content '{oldContent}'"); + + return newContent; + } - protected void RemoveContentsFromProjectFile(string pathRelativeToProjectDir, string afterMarker, string beforeMarker) + protected void UpdateBrowserProgramFile() => + UpdateFile("Program.cs", browserProgramReplacements); + + protected void UpdateFile(string pathRelativeToProjectDir, Dictionary replacements) + { + var path = Path.Combine(_projectDir!, pathRelativeToProjectDir); + string text = File.ReadAllText(path); + foreach (var replacement in replacements) { - var path = Path.Combine(_projectDir!, pathRelativeToProjectDir); - string text = File.ReadAllText(path); - int start = text.IndexOf(afterMarker); - int end = text.IndexOf(beforeMarker, start); - if (start == -1 || end == -1) - throw new XunitException($"Start or end marker not found in '{path}'"); - start += afterMarker.Length; - text = text.Remove(start, end - start); - // separate the markers with a new line - text = text.Insert(start, "\n"); - File.WriteAllText(path, text); + text = StringReplaceWithAssert(text, replacement.Key, replacement.Value); } + File.WriteAllText(path, text); + } - protected void UpdateBrowserMainJs(string targetFramework, string runtimeAssetsRelativePath = DefaultRuntimeAssetsRelativePath) - { - base.UpdateBrowserMainJs( - (mainJsContent) => - { - // .withExitOnUnhandledError() is available only only >net7.0 - mainJsContent = StringReplaceWithAssert( - mainJsContent, - ".create()", - (targetFramework == "net8.0" || targetFramework == "net9.0") - ? ".withConsoleForwarding().withElementOnExit().withExitCodeLogging().withExitOnUnhandledError().create()" - : ".withConsoleForwarding().withElementOnExit().withExitCodeLogging().create()" - ); - - // dotnet.run() is already used in <= net8.0 - if (targetFramework != "net8.0") - mainJsContent = StringReplaceWithAssert(mainJsContent, "runMain()", "dotnet.run()"); - - mainJsContent = StringReplaceWithAssert(mainJsContent, "from './_framework/dotnet.js'", $"from '{runtimeAssetsRelativePath}dotnet.js'"); - - return mainJsContent; - }, - targetFramework, - runtimeAssetsRelativePath + protected void RemoveContentsFromProjectFile(string pathRelativeToProjectDir, string afterMarker, string beforeMarker) + { + var path = Path.Combine(_projectDir!, pathRelativeToProjectDir); + string text = File.ReadAllText(path); + int start = text.IndexOf(afterMarker); + int end = text.IndexOf(beforeMarker, start); + if (start == -1 || end == -1) + throw new XunitException($"Start or end marker not found in '{path}'"); + start += afterMarker.Length; + text = text.Remove(start, end - start); + // separate the markers with a new line + text = text.Insert(start, "\n"); + File.WriteAllText(path, text); + } + + protected void UpdateBrowserMainJs(string targetFramework = DefaultTargetFramework, string runtimeAssetsRelativePath = DefaultRuntimeAssetsRelativePath) + { + string mainJsPath = Path.Combine(_projectDir!, "wwwroot", "main.js"); + string mainJsContent = File.ReadAllText(mainJsPath); + + string updatedMainJsContent = StringReplaceWithAssert( + mainJsContent, + ".create()", + (targetFramework == "net8.0" || targetFramework == "net9.0") + ? ".withConsoleForwarding().withElementOnExit().withExitCodeLogging().withExitOnUnhandledError().create()" + : ".withConsoleForwarding().withElementOnExit().withExitCodeLogging().create()" ); - } - protected void UpdateMainJsEnvironmentVariables(params (string key, string value)[] variables) - { - string mainJsPath = Path.Combine(_projectDir!, "main.mjs"); - string mainJsContent = File.ReadAllText(mainJsPath); + // dotnet.run() is already used in <= net8.0 + if (targetFramework != "net8.0") + updatedMainJsContent = StringReplaceWithAssert(updatedMainJsContent, "runMain()", "dotnet.run()"); - StringBuilder js = new(); - foreach (var variable in variables) - { - js.Append($".withEnvironmentVariable(\"{variable.key}\", \"{variable.value}\")"); - } + updatedMainJsContent = StringReplaceWithAssert(updatedMainJsContent, "from './_framework/dotnet.js'", $"from '{runtimeAssetsRelativePath}dotnet.js'"); - mainJsContent = StringReplaceWithAssert(mainJsContent, ".create()", js.ToString() + ".create()"); - File.WriteAllText(mainJsPath, mainJsContent); - } + File.WriteAllText(mainJsPath, updatedMainJsContent); + } - protected string RunConsole(BuildArgs buildArgs, int expectedExitCode = 42, string language = "en-US") - { - CommandResult res = new RunCommand(s_buildEnv, _testOutput) - .WithWorkingDirectory(_projectDir!) - .WithEnvironmentVariable("LANG", language) - .ExecuteWithCapturedOutput($"run --no-silent --no-build -c {buildArgs.Config}") - .EnsureExitCode(expectedExitCode); - return res.Output; - } + protected void UpdateMainJsEnvironmentVariables(params (string key, string value)[] variables) + { + string mainJsPath = Path.Combine(_projectDir!, "main.mjs"); + string mainJsContent = File.ReadAllText(mainJsPath); - protected async Task RunBrowser(string config, string projectFile, string language = "en-US") + StringBuilder js = new(); + foreach (var variable in variables) { - using var runCommand = new RunCommand(s_buildEnv, _testOutput) - .WithWorkingDirectory(_projectDir!); - - await using var runner = new BrowserRunner(_testOutput); - var page = await runner.RunAsync(runCommand, $"run --no-silent -c {config} --no-build --project \"{projectFile}\" --forward-console", language: language); - await runner.WaitForExitMessageAsync(TimeSpan.FromMinutes(2)); - Assert.Contains("WASM EXIT 42", string.Join(Environment.NewLine, runner.OutputLines)); - return string.Join("\n", runner.OutputLines); + js.Append($".withEnvironmentVariable(\"{variable.key}\", \"{variable.value}\")"); } + + mainJsContent = StringReplaceWithAssert(mainJsContent, ".create()", js.ToString() + ".create()"); + + File.WriteAllText(mainJsPath, mainJsContent); } + + // ToDo: consolidate with BlazorRunTest + protected async Task RunBuiltBrowserApp(string config, string projectFile, string language = "en-US", string extraArgs = "", string testScenario = "") + => await RunBrowser( + $"run --no-silent -c {config} --no-build --project \"{projectFile}\" --forward-console {extraArgs}", + _projectDir!, + language, + testScenario: testScenario); + + protected async Task RunPublishedBrowserApp(string config, string language = "en-US", string extraArgs = "", string testScenario = "") + => await RunBrowser( + command: $"{s_xharnessRunnerCommand} wasm webserver --app=. --web-server-use-default-files", + workingDirectory: Path.Combine(FindBinFrameworkDir(config, forPublish: true), ".."), + language: language, + testScenario: testScenario); + + private async Task RunBrowser(string command, string workingDirectory, string language = "en-US", string testScenario = "") + { + using var runCommand = new RunCommand(s_buildEnv, _testOutput).WithWorkingDirectory(workingDirectory); + await using var runner = new BrowserRunner(_testOutput); + Func? modifyBrowserUrl = string.IsNullOrEmpty(testScenario) ? + null : + browserUrl => new Uri(new Uri(browserUrl), $"?test={testScenario}").ToString(); + var page = await runner.RunAsync(runCommand, command, language: language, modifyBrowserUrl: modifyBrowserUrl); + await runner.WaitForExitMessageAsync(TimeSpan.FromMinutes(2)); + Assert.Contains("WASM EXIT 42", string.Join(Environment.NewLine, runner.OutputLines)); + return string.Join("\n", runner.OutputLines); + } + + public string FindBinFrameworkDir(string config, bool forPublish, string framework = DefaultTargetFramework, string? projectDir = null) => + _provider.FindBinFrameworkDir(config: config, forPublish: forPublish, framework: framework, projectDir: projectDir); } diff --git a/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/AppTestBase.cs b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/AppTestBase.cs index f54dc2ebca348f..71411e7c4dadf6 100644 --- a/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/AppTestBase.cs +++ b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/AppTestBase.cs @@ -37,23 +37,6 @@ protected void CopyTestAsset(string assetName, string generatedProjectNamePrefix } } - protected void BlazorHostedBuild( - string config, - string assetName, - string projectDirSuffix, - string clientDirRelativeToProjectDir = "", - string? generatedProjectNamePrefix = null, - RuntimeVariant runtimeType = RuntimeVariant.SingleThreaded) - { - CopyTestAsset(assetName, generatedProjectNamePrefix, projectDirSuffix); - string frameworkDir = FindBlazorHostedBinFrameworkDir(config, - forPublish: false, - clientDirRelativeToProjectDir: clientDirRelativeToProjectDir); - BuildProject(configuration: config, - binFrameworkDir: frameworkDir, - runtimeType: runtimeType); - } - protected void BuildProject( string configuration, string? binFrameworkDir = null, @@ -97,10 +80,6 @@ protected void PublishProject( result.EnsureSuccessful(); } - protected ToolCommand CreateDotNetCommand() => new DotNetCommand(s_buildEnv, _testOutput) - .WithWorkingDirectory(_projectDir!) - .WithEnvironmentVariable("NUGET_PACKAGES", _nugetPackagesDir); - protected Task RunSdkStyleAppForBuild(RunOptions options) => RunSdkStyleApp(options, BlazorRunHost.DotnetRun); diff --git a/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/DebugLevelTestsBase.cs b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/DebugLevelTestsBase.cs deleted file mode 100644 index cac95e26fa3f20..00000000000000 --- a/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/DebugLevelTestsBase.cs +++ /dev/null @@ -1,86 +0,0 @@ -// 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.Linq; -using System.Threading.Tasks; -using Xunit; -using Xunit.Abstractions; - -#nullable enable - -namespace Wasm.Build.Tests.TestAppScenarios; - -public abstract class DebugLevelTestsBase : AppTestBase -{ - public DebugLevelTestsBase(ITestOutputHelper output, SharedBuildPerTestClassFixture buildContext) - : base(output, buildContext) - { - } - - protected void AssertDebugLevel(RunResult result, int value) - { - Assert.Collection( - result.TestOutput, - m => Assert.Equal($"WasmDebugLevel: {value}", m) - ); - } - - protected abstract void SetupProject(string projectId); - protected abstract Task RunForBuild(string configuration); - protected abstract Task RunForPublish(string configuration); - - [Theory] - [InlineData("Debug")] - [InlineData("Release")] - public async Task BuildWithDefaultLevel(string configuration) - { - SetupProject($"DebugLevelTests_BuildWithDefaultLevel_{configuration}"); - BuildProject(configuration, assertAppBundle: false); - - var result = await RunForBuild(configuration); - AssertDebugLevel(result, -1); - } - - [Theory] - [InlineData("Debug", 1)] - [InlineData("Release", 1)] - [InlineData("Debug", 0)] - [InlineData("Release", 0)] - public async Task BuildWithExplicitValue(string configuration, int debugLevel) - { - SetupProject($"DebugLevelTests_BuildWithExplicitValue_{configuration}"); - BuildProject(configuration, assertAppBundle: false, extraArgs: $"-p:WasmDebugLevel={debugLevel}"); - - var result = await RunForBuild(configuration); - AssertDebugLevel(result, debugLevel); - } - - [Theory] - [InlineData("Debug")] - [InlineData("Release")] - public async Task PublishWithDefaultLevel(string configuration) - { - SetupProject($"DebugLevelTests_PublishWithDefaultLevel_{configuration}"); - PublishProject(configuration, assertAppBundle: false); - - var result = await RunForPublish(configuration); - AssertDebugLevel(result, 0); - } - - [Theory] - [InlineData("Debug", 1)] - [InlineData("Release", 1)] - [InlineData("Debug", -1)] - [InlineData("Release", -1)] - public async Task PublishWithExplicitValue(string configuration, int debugLevel) - { - SetupProject($"DebugLevelTests_PublishWithExplicitValue_{configuration}"); - PublishProject(configuration, assertAppBundle: false, extraArgs: $"-p:WasmDebugLevel={debugLevel}"); - - var result = await RunForPublish(configuration); - AssertDebugLevel(result, debugLevel); - } -} diff --git a/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/WasmAppBuilderDebugLevelTests.cs b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/WasmAppBuilderDebugLevelTests.cs deleted file mode 100644 index bf8c3272960b36..00000000000000 --- a/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/WasmAppBuilderDebugLevelTests.cs +++ /dev/null @@ -1,70 +0,0 @@ -// 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.Linq; -using System.Threading.Tasks; -using Xunit; -using Xunit.Abstractions; - -#nullable enable - -namespace Wasm.Build.Tests.TestAppScenarios; - -public class WasmAppBuilderDebugLevelTests : DebugLevelTestsBase -{ - public WasmAppBuilderDebugLevelTests(ITestOutputHelper output, SharedBuildPerTestClassFixture buildContext) - : base(output, buildContext) - { - } - - protected override void SetupProject(string projectId) - { - Id = $"{projectId}_{GetRandomId()}"; - string projectfile = CreateWasmTemplateProject(Id, "wasmconsole"); - string projectDir = Path.GetDirectoryName(projectfile)!; - string mainJs = Path.Combine(projectDir, "main.mjs"); - string mainJsContent = File.ReadAllText(mainJs); - mainJsContent = mainJsContent - .Replace("import { dotnet }", "import { dotnet, exit }") - .Replace("await runMainAndExit()", "console.log('TestOutput -> WasmDebugLevel: ' + config.debugLevel); exit(0)"); - File.WriteAllText(mainJs, mainJsContent); - } - - protected override Task RunForBuild(string configuration) - { - using RunCommand cmd = new RunCommand(s_buildEnv, _testOutput); - CommandResult res = cmd.WithWorkingDirectory(_projectDir!) - .ExecuteWithCapturedOutput($"run --no-silent --no-build -c {configuration}"); - - return Task.FromResult(ProcessRunOutput(res)); - } - - private RunResult ProcessRunOutput(CommandResult res) - { - var output = res.Output.Split(Environment.NewLine); - _testOutput.WriteLine($"DEBUG: parsed lines '{String.Join(", ", output)}'"); - - var prefix = "[] TestOutput -> "; - var testOutput = output - .Where(l => l.StartsWith(prefix)) - .Select(l => l.Substring(prefix.Length)) - .ToArray(); - - _testOutput.WriteLine($"DEBUG: testOutput '{String.Join(", ", testOutput)}'"); - return new RunResult(res.ExitCode, testOutput, output, []); - } - - protected override Task RunForPublish(string configuration) - { - // WasmAppBuilder does publish to the same folder as build (it overrides the output), - // and thus using dotnet run work correctly for publish as well. - using RunCommand cmd = new RunCommand(s_buildEnv, _testOutput); - CommandResult res = cmd.WithWorkingDirectory(_projectDir!) - .ExecuteWithCapturedOutput($"run --no-silent --no-build -c {configuration}"); - - return Task.FromResult(ProcessRunOutput(res)); - } -} diff --git a/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/WasmSdkDebugLevelTests.cs b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/WasmSdkDebugLevelTests.cs deleted file mode 100644 index b3d1a0316c49e6..00000000000000 --- a/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/WasmSdkDebugLevelTests.cs +++ /dev/null @@ -1,46 +0,0 @@ -// 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.Linq; -using System.Threading.Tasks; -using Xunit; -using Xunit.Abstractions; - -#nullable enable - -namespace Wasm.Build.Tests.TestAppScenarios; - -public class WasmSdkDebugLevelTests : DebugLevelTestsBase -{ - public WasmSdkDebugLevelTests(ITestOutputHelper output, SharedBuildPerTestClassFixture buildContext) - : base(output, buildContext) - { - } - - protected override void SetupProject(string projectId) => CopyTestAsset("WasmBasicTestApp", projectId, "App"); - - protected override Task RunForBuild(string configuration) => RunSdkStyleAppForBuild(new( - Configuration: configuration, - TestScenario: "DebugLevelTest" - )); - - protected override Task RunForPublish(string configuration) => RunSdkStyleAppForPublish(new( - Configuration: configuration, - TestScenario: "DebugLevelTest" - )); - - [Theory] - [InlineData("Debug")] - [InlineData("Release")] - public async Task PublishWithDefaultLevelAndPdbs(string configuration) - { - SetupProject($"DebugLevelTests_PublishWithDefaultLevelAndPdbs_{configuration}"); - PublishProject(configuration, assertAppBundle: false, extraArgs: $"-p:CopyOutputSymbolsToPublishDirectory=true"); - - var result = await RunForPublish(configuration); - AssertDebugLevel(result, -1); - } -} diff --git a/src/mono/wasm/Wasm.Build.Tests/TestMainJsProjectProvider.cs b/src/mono/wasm/Wasm.Build.Tests/TestMainJsProjectProvider.cs index 39b1effac58671..b14d52ac4f1824 100644 --- a/src/mono/wasm/Wasm.Build.Tests/TestMainJsProjectProvider.cs +++ b/src/mono/wasm/Wasm.Build.Tests/TestMainJsProjectProvider.cs @@ -14,9 +14,8 @@ public class TestMainJsProjectProvider : ProjectProviderBase { public TestMainJsProjectProvider(ITestOutputHelper _testOutput, string? _projectDir = null) : base(_testOutput, _projectDir) - { - BundleDirName = "AppBundle"; - } + { } + protected override string BundleDirName { get { return "AppBundle"; } } // no fingerprinting protected override IReadOnlyDictionary GetAllKnownDotnetFilesToFingerprintMap(AssertBundleOptionsBase assertOptions) @@ -112,9 +111,9 @@ public void AssertBundle(BuildArgs buildArgs, BuildProjectOptions buildProjectOp AssertBundle(assertOptions); } - public override string FindBinFrameworkDir(string config, bool forPublish, string framework, string? bundleDirName = null, string? projectDir = null) + public override string FindBinFrameworkDir(string config, bool forPublish, string framework, string? projectDir = null) { EnsureProjectDirIsSet(); - return Path.Combine(projectDir ?? ProjectDir!, "bin", config, framework, "browser-wasm", bundleDirName ?? this.BundleDirName, "_framework"); + return Path.Combine(projectDir ?? ProjectDir!, "bin", config, framework, "browser-wasm", BundleDirName, "_framework"); } } diff --git a/src/mono/wasm/Wasm.Build.Tests/WasmBuildAppTest.cs b/src/mono/wasm/Wasm.Build.Tests/WasmBuildAppTest.cs index 19e1e08941e717..cfff7b40ba0ba9 100644 --- a/src/mono/wasm/Wasm.Build.Tests/WasmBuildAppTest.cs +++ b/src/mono/wasm/Wasm.Build.Tests/WasmBuildAppTest.cs @@ -124,7 +124,7 @@ public void PropertiesFromRuntimeConfigJson(BuildArgs buildArgs, RunHost host, s File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), programText); File.WriteAllText(Path.Combine(_projectDir!, "runtimeconfig.template.json"), runtimeConfigTemplateJson); }, - DotnetWasmFromRuntimePack: !(buildArgs.AOT || buildArgs.Config == "Release"))); + DotnetWasmFromRuntimePack: IsDotnetWasmFromRuntimePack(buildArgs))); RunAndTestWasmApp(buildArgs, expectedExitCode: 42, test: output => Assert.Contains("test_runtimeconfig_json: 25", output), host: host, id: id); @@ -153,7 +153,7 @@ public void PropertiesFromCsproj(BuildArgs buildArgs, RunHost host, string id) { File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), programText); }, - DotnetWasmFromRuntimePack: !(buildArgs.AOT || buildArgs.Config == "Release"))); + DotnetWasmFromRuntimePack: IsDotnetWasmFromRuntimePack(buildArgs))); RunAndTestWasmApp(buildArgs, expectedExitCode: 42, test: output => Assert.Contains("System.Threading.ThreadPool.MaxThreads: 20", output), host: host, id: id); @@ -185,7 +185,7 @@ protected void TestMain(string projectName, buildArgs = ExpandBuildArgs(buildArgs, extraProperties); if (dotnetWasmFromRuntimePack == null) - dotnetWasmFromRuntimePack = !(buildArgs.AOT || buildArgs.Config == "Release"); + dotnetWasmFromRuntimePack = IsDotnetWasmFromRuntimePack(buildArgs); BuildProject(buildArgs, id: id, diff --git a/src/mono/wasm/Wasm.Build.Tests/WasmSdkBasedProjectProvider.cs b/src/mono/wasm/Wasm.Build.Tests/WasmSdkBasedProjectProvider.cs index 16108e5af24ec0..06d47877717507 100644 --- a/src/mono/wasm/Wasm.Build.Tests/WasmSdkBasedProjectProvider.cs +++ b/src/mono/wasm/Wasm.Build.Tests/WasmSdkBasedProjectProvider.cs @@ -15,11 +15,14 @@ namespace Wasm.Build.Tests; public class WasmSdkBasedProjectProvider : ProjectProviderBase { - public WasmSdkBasedProjectProvider(ITestOutputHelper _testOutput, string? _projectDir = null) + private readonly string _defaultTargetFramework; + public WasmSdkBasedProjectProvider(ITestOutputHelper _testOutput, string defaultTargetFramework, string? _projectDir = null) : base(_testOutput, _projectDir) { + _defaultTargetFramework = defaultTargetFramework; IsFingerprintingSupported = true; } + protected override string BundleDirName { get { return "wwwroot"; } } protected override IReadOnlyDictionary GetAllKnownDotnetFilesToFingerprintMap(AssertBundleOptionsBase assertOptions) => new SortedDictionary() @@ -66,13 +69,15 @@ protected override IReadOnlySet GetDotNetFilesExpectedSet(AssertBundleOp } - public void AssertBundle(BuildArgs buildArgs, BuildProjectOptions buildProjectOptions) + protected void AssertBundle(BuildArgs buildArgs, BuildProjectOptions buildProjectOptions) { + string frameworkDir = buildProjectOptions.BinFrameworkDir ?? + FindBinFrameworkDir(buildArgs.Config, buildProjectOptions.Publish, buildProjectOptions.TargetFramework); AssertBundle(new( Config: buildArgs.Config, IsPublish: buildProjectOptions.Publish, TargetFramework: buildProjectOptions.TargetFramework, - BinFrameworkDir: buildProjectOptions.BinFrameworkDir ?? FindBinFrameworkDir(buildArgs.Config, buildProjectOptions.Publish, buildProjectOptions.TargetFramework), + BinFrameworkDir: frameworkDir, CustomIcuFile: buildProjectOptions.CustomIcuFile, GlobalizationMode: buildProjectOptions.GlobalizationMode, AssertSymbolsFile: false, @@ -80,7 +85,7 @@ public void AssertBundle(BuildArgs buildArgs, BuildProjectOptions buildProjectOp )); } - public void AssertBundle(AssertWasmSdkBundleOptions assertOptions) + protected void AssertBundle(AssertWasmSdkBundleOptions assertOptions) { IReadOnlyDictionary actualDotnetFiles = AssertBasicBundle(assertOptions); @@ -147,4 +152,42 @@ public void AssertBundle(AssertWasmSdkBundleOptions assertOptions) } } } -} + + public void AssertTestMainJsBundle(BuildArgs buildArgs, + BuildProjectOptions buildProjectOptions, + string? buildOutput = null, + AssertTestMainJsAppBundleOptions? assertAppBundleOptions = null) + { + if (buildOutput is not null) + ProjectProviderBase.AssertRuntimePackPath(buildOutput, buildProjectOptions.TargetFramework ?? _defaultTargetFramework); + + if (assertAppBundleOptions is not null) + AssertBundle(assertAppBundleOptions); + else + AssertBundle(buildArgs, buildProjectOptions); + } + + public void AssertWasmSdkBundle(BuildArgs buildArgs, + BuildProjectOptions buildProjectOptions, + string? buildOutput = null, + AssertWasmSdkBundleOptions? assertAppBundleOptions = null) + { + if (buildOutput is not null) + ProjectProviderBase.AssertRuntimePackPath(buildOutput, buildProjectOptions.TargetFramework ?? _defaultTargetFramework); + + if (assertAppBundleOptions is not null) + AssertBundle(assertAppBundleOptions); + else + AssertBundle(buildArgs, buildProjectOptions); + } + + public override string FindBinFrameworkDir(string config, bool forPublish, string framework, string? projectDir = null) + { + EnsureProjectDirIsSet(); + string basePath = Path.Combine(projectDir ?? ProjectDir!, "bin", config, framework); + if (forPublish) + basePath = FindSubDirIgnoringCase(basePath, "publish"); + + return Path.Combine(basePath, BundleDirName, "_framework"); + } +} \ No newline at end of file diff --git a/src/mono/wasm/Wasm.Build.Tests/WasmTemplateTestBase.cs b/src/mono/wasm/Wasm.Build.Tests/WasmTemplateTestBase.cs deleted file mode 100644 index 2906541e45aed5..00000000000000 --- a/src/mono/wasm/Wasm.Build.Tests/WasmTemplateTestBase.cs +++ /dev/null @@ -1,157 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -#nullable enable - -using System; -using System.Collections.Generic; -using System.IO; -using System.Text.Json.Nodes; -using Xunit.Abstractions; - -namespace Wasm.Build.Tests; - -public abstract class WasmTemplateTestBase : BuildTestBase -{ - private readonly WasmSdkBasedProjectProvider _provider; - protected WasmTemplateTestBase(ITestOutputHelper output, SharedBuildPerTestClassFixture buildContext, WasmSdkBasedProjectProvider? projectProvider = null) - : base(projectProvider ?? new WasmSdkBasedProjectProvider(output), output, buildContext) - { - _provider = GetProvider(); - // Wasm templates are not using wasm sdk yet - _provider.BundleDirName = "AppBundle"; - } - - public string CreateWasmTemplateProject(string id, string template = "wasmbrowser", string extraArgs = "", bool runAnalyzers = true, bool addFrameworkArg = false, string? extraProperties = null) - { - InitPaths(id); - InitProjectDir(_projectDir, addNuGetSourceForLocalPackages: true); - - File.WriteAllText(Path.Combine(_projectDir, "Directory.Build.props"), ""); - File.WriteAllText(Path.Combine(_projectDir, "Directory.Build.targets"), - """ - - - - - - - - """); - if (UseWBTOverridePackTargets) - File.Copy(BuildEnvironment.WasmOverridePacksTargetsPath, Path.Combine(_projectDir, Path.GetFileName(BuildEnvironment.WasmOverridePacksTargetsPath)), overwrite: true); - - if (addFrameworkArg) - extraArgs += $" -f {DefaultTargetFramework}"; - using DotNetCommand cmd = new DotNetCommand(s_buildEnv, _testOutput, useDefaultArgs: false); - CommandResult result = cmd.WithWorkingDirectory(_projectDir!) - .ExecuteWithCapturedOutput($"new {template} {extraArgs}") - .EnsureSuccessful(); - - string projectfile = Path.Combine(_projectDir!, $"{id}.csproj"); - - if (extraProperties == null) - extraProperties = string.Empty; - - extraProperties += "true"; - if (runAnalyzers) - extraProperties += "true"; - - if (template == "wasmconsole") - { - UpdateRuntimeconfigTemplateForNode(_projectDir); - } - - AddItemsPropertiesToProject(projectfile, extraProperties); - - return projectfile; - } - - private static void UpdateRuntimeconfigTemplateForNode(string projectDir) - { - // TODO: Can be removed once Node >= 20 - - string runtimeconfigTemplatePath = Path.Combine(projectDir, "runtimeconfig.template.json"); - string runtimeconfigTemplateContent = File.ReadAllText(runtimeconfigTemplatePath); - var runtimeconfigTemplate = JsonObject.Parse(runtimeconfigTemplateContent); - if (runtimeconfigTemplate == null) - throw new Exception($"Unable to parse runtimeconfigtemplate at '{runtimeconfigTemplatePath}'"); - - var perHostConfigs = runtimeconfigTemplate?["wasmHostProperties"]?["perHostConfig"]?.AsArray(); - if (perHostConfigs == null || perHostConfigs.Count == 0 || perHostConfigs[0] == null) - throw new Exception($"Unable to find perHostConfig in runtimeconfigtemplate at '{runtimeconfigTemplatePath}'"); - - perHostConfigs[0]!["host-args"] = new JsonArray( - "--experimental-wasm-simd", - "--experimental-wasm-eh" - ); - - File.WriteAllText(runtimeconfigTemplatePath, runtimeconfigTemplate!.ToString()); - } - - public (string projectDir, string buildOutput) BuildTemplateProject(BuildArgs buildArgs, - string id, - BuildProjectOptions buildProjectOptions) - { - if (buildProjectOptions.ExtraBuildEnvironmentVariables is null) - buildProjectOptions = buildProjectOptions with { ExtraBuildEnvironmentVariables = new Dictionary() }; - - // TODO: reenable this when the SDK supports targetting net10.0 - //buildProjectOptions.ExtraBuildEnvironmentVariables["TreatPreviousAsCurrent"] = "false"; - - (CommandResult res, string logFilePath) = BuildProjectWithoutAssert(id, buildArgs.Config, buildProjectOptions); - if (buildProjectOptions.UseCache) - _buildContext.CacheBuild(buildArgs, new BuildProduct(_projectDir!, logFilePath, true, res.Output)); - - if (buildProjectOptions.AssertAppBundle) - { - if (buildProjectOptions.IsBrowserProject) - AssertWasmSdkBundle(buildArgs, buildProjectOptions, res.Output); - else - AssertTestMainJsBundle(buildArgs, buildProjectOptions, res.Output); - } - return (_projectDir!, res.Output); - } - - public void AssertTestMainJsBundle(BuildArgs buildArgs, - BuildProjectOptions buildProjectOptions, - string? buildOutput = null, - AssertTestMainJsAppBundleOptions? assertAppBundleOptions = null) - { - if (buildOutput is not null) - ProjectProviderBase.AssertRuntimePackPath(buildOutput, buildProjectOptions.TargetFramework ?? DefaultTargetFramework); - - var testMainJsProvider = new TestMainJsProjectProvider(_testOutput, _projectDir!); - if (assertAppBundleOptions is not null) - testMainJsProvider.AssertBundle(assertAppBundleOptions); - else - testMainJsProvider.AssertBundle(buildArgs, buildProjectOptions); - } - - public void AssertWasmSdkBundle(BuildArgs buildArgs, - BuildProjectOptions buildProjectOptions, - string? buildOutput = null, - AssertWasmSdkBundleOptions? assertAppBundleOptions = null) - { - if (buildOutput is not null) - ProjectProviderBase.AssertRuntimePackPath(buildOutput, buildProjectOptions.TargetFramework ?? DefaultTargetFramework); - - var projectProvider = new WasmSdkBasedProjectProvider(_testOutput, _projectDir!); - if (assertAppBundleOptions is not null) - projectProvider.AssertBundle(assertAppBundleOptions); - else - projectProvider.AssertBundle(buildArgs, buildProjectOptions); - } - - protected const string DefaultRuntimeAssetsRelativePath = "./_framework/"; - - protected void UpdateBrowserMainJs(Func transform, string targetFramework, string runtimeAssetsRelativePath = DefaultRuntimeAssetsRelativePath) - { - string mainJsPath = Path.Combine(_projectDir!, "wwwroot", "main.js"); - string mainJsContent = File.ReadAllText(mainJsPath); - - mainJsContent = transform(mainJsContent); - - File.WriteAllText(mainJsPath, mainJsContent); - } -} diff --git a/src/mono/wasm/testassets/WasmBasicTestApp/App/wwwroot/main.js b/src/mono/wasm/testassets/WasmBasicTestApp/App/wwwroot/main.js index d92d72874ea66b..bc9cc730a364e9 100644 --- a/src/mono/wasm/testassets/WasmBasicTestApp/App/wwwroot/main.js +++ b/src/mono/wasm/testassets/WasmBasicTestApp/App/wwwroot/main.js @@ -190,7 +190,7 @@ try { break; case "DebugLevelTest": testOutput("WasmDebugLevel: " + config.debugLevel); - exit(0); + exit(42); break; case "InterpPgoTest": setModuleImports('main.js', { diff --git a/src/mono/wasm/testassets/marshal_ilgen_test.cs b/src/mono/wasm/testassets/marshal_ilgen_test.cs index ef4572b62f4bd1..1c52a8b5ee3497 100644 --- a/src/mono/wasm/testassets/marshal_ilgen_test.cs +++ b/src/mono/wasm/testassets/marshal_ilgen_test.cs @@ -2,26 +2,15 @@ using System.Runtime.InteropServices; using System.Runtime.InteropServices.JavaScript; -Console.WriteLine("Hello, Console!"); +int[] x = new int[0]; +MyClass.call_needing_marhsal_ilgen(x); +Console.WriteLine("call_needing_marhsal_ilgen got called"); -return 0; +return 42; public partial class MyClass { - [JSExport] - internal static string Greeting() - { - int[] x = new int[0]; - call_needing_marhsal_ilgen(x); - - var text = $"Hello, World! Greetings from node version: {GetNodeVersion()}"; - return text; - } - - [JSImport("node.process.version", "main.mjs")] - internal static partial string GetNodeVersion(); - [DllImport("incompatible_type")] - static extern void call_needing_marhsal_ilgen(int[] numbers); + public static extern void call_needing_marhsal_ilgen(int[] numbers); }