From 5f778101c6867f1490889658cd27095cded236fe Mon Sep 17 00:00:00 2001 From: Ankit Jain Date: Tue, 22 Jun 2021 12:35:38 -0400 Subject: [PATCH] [wasm] Collect, and process satellite assemblies automatically (#53656) --- eng/testing/tests.wasm.targets | 19 +- src/mono/wasm/build/WasmApp.Native.targets | 4 +- src/mono/wasm/build/WasmApp.targets | 16 +- .../aot-tests/ProxyProjectForAOTOnHelix.proj | 8 +- src/tasks/WasmAppBuilder/WasmAppBuilder.cs | 7 + .../Wasm.Build.Tests/BuildTestBase.cs | 57 ++++-- .../InvariantGlobalizationTests.cs | 6 +- .../Wasm.Build.Tests/MainWithArgsTests.cs | 2 +- .../Wasm.Build.Tests/NativeBuildTests.cs | 4 +- .../Wasm.Build.Tests/RebuildTests.cs | 2 +- .../SatelliteAssembliesTests.cs | 179 ++++++++++++++++++ .../SharedBuildPerTestClassFixture.cs | 4 +- .../Wasm.Build.Tests/Wasm.Build.Tests.csproj | 5 +- .../Wasm.Build.Tests/WasmBuildAppTest.cs | 9 +- .../testassets/LibraryWithResources/Class1.cs | 11 ++ .../Directory.Build.props | 1 + .../Directory.Build.targets | 1 + .../LibraryWithResources.csproj | 10 + .../testassets/resx/words.es-ES.resx | 127 +++++++++++++ .../testassets/resx/words.ja-JP.resx | 127 +++++++++++++ .../BuildWasmApps/testassets/resx/words.resx | 127 +++++++++++++ 21 files changed, 672 insertions(+), 54 deletions(-) create mode 100644 src/tests/BuildWasmApps/Wasm.Build.Tests/SatelliteAssembliesTests.cs create mode 100644 src/tests/BuildWasmApps/testassets/LibraryWithResources/Class1.cs create mode 100644 src/tests/BuildWasmApps/testassets/LibraryWithResources/Directory.Build.props create mode 100644 src/tests/BuildWasmApps/testassets/LibraryWithResources/Directory.Build.targets create mode 100644 src/tests/BuildWasmApps/testassets/LibraryWithResources/LibraryWithResources.csproj create mode 100644 src/tests/BuildWasmApps/testassets/resx/words.es-ES.resx create mode 100644 src/tests/BuildWasmApps/testassets/resx/words.ja-JP.resx create mode 100644 src/tests/BuildWasmApps/testassets/resx/words.resx diff --git a/eng/testing/tests.wasm.targets b/eng/testing/tests.wasm.targets index 1e1c8669579..de4432bee9f 100644 --- a/eng/testing/tests.wasm.targets +++ b/eng/testing/tests.wasm.targets @@ -69,8 +69,7 @@ - - + @@ -131,17 +130,17 @@ -1 - - - + + <_SatelliteAssemblies Include="$(PublishDir)*\*.resources.dll" /> + <_SatelliteAssemblies CultureName="$([System.IO.Directory]::GetParent('%(Identity)').Name)" /> + <_SatelliteAssemblies TargetPath="%(CultureName)\%(FileName)%(Extension)" /> - + + + + - <_CopyLocalPaths Include="@(PublishItemsOutputGroupOutputs)" diff --git a/src/mono/wasm/build/WasmApp.Native.targets b/src/mono/wasm/build/WasmApp.Native.targets index b16195a618a..b6897fbd2b4 100644 --- a/src/mono/wasm/build/WasmApp.Native.targets +++ b/src/mono/wasm/build/WasmApp.Native.targets @@ -353,6 +353,7 @@ EMSCRIPTEN_KEEPALIVE void mono_wasm_load_profiler_aot (const char *desc) { mono_ @(MonoAOTCompilerDefaultAotArguments, ';') @(MonoAOTCompilerDefaultProcessArguments, ';') + <_AOT_InternalForceInterpretAssemblies Include="@(_WasmAssembliesInternal->WithMetadataValue('_InternalForceInterpret', 'true'))" /> <_WasmAssembliesInternal Remove="@(_WasmAssembliesInternal)" /> @@ -422,9 +423,6 @@ EMSCRIPTEN_KEEPALIVE void mono_wasm_load_profiler_aot (const char *desc) { mono_ <_WasmNativeFileForLinking Include="@(_BitcodeFile)" /> - - diff --git a/src/mono/wasm/build/WasmApp.targets b/src/mono/wasm/build/WasmApp.targets index b886f327d71..03428743689 100644 --- a/src/mono/wasm/build/WasmApp.targets +++ b/src/mono/wasm/build/WasmApp.targets @@ -61,7 +61,6 @@ Public items: - @(WasmExtraFilesToDeploy) - Files to copy to $(WasmAppDir). (relative path can be set via %(TargetPath) metadata) - - @(WasmSatelliteAssemblies) - @(WasmFilesToIncludeInFileSystem) - Files to include in the vfs - @(WasmNativeAsset) - Native files to be added to `NativeAssets` in the bundle. @@ -115,6 +114,13 @@ <_WasmAssembliesInternal Include="@(WasmAssembliesToBundle->Distinct())" /> + + <_WasmSatelliteAssemblies Include="@(_WasmAssembliesInternal)" /> + <_WasmSatelliteAssemblies Remove="@(_WasmSatelliteAssemblies)" Condition="!$([System.String]::Copy('%(Identity)').EndsWith('.resources.dll'))" /> + + <_WasmSatelliteAssemblies CultureName="$([System.IO.Directory]::GetParent('%(Identity)').Name)" /> + + <_WasmAssembliesInternal Remove="@(_WasmSatelliteAssemblies)" /> @@ -142,7 +148,7 @@ MainJS="$(WasmMainJSPath)" Assemblies="@(_WasmAssembliesInternal)" InvariantGlobalization="$(InvariantGlobalization)" - SatelliteAssemblies="@(WasmSatelliteAssemblies)" + SatelliteAssemblies="@(_WasmSatelliteAssemblies)" FilesToIncludeInFileSystem="@(WasmFilesToIncludeInFileSystem)" IcuDataFileName="$(WasmIcuDataFileName)" RemoteSources="@(WasmRemoteSources)" @@ -193,11 +199,5 @@ - - - diff --git a/src/mono/wasm/data/aot-tests/ProxyProjectForAOTOnHelix.proj b/src/mono/wasm/data/aot-tests/ProxyProjectForAOTOnHelix.proj index 0a0b915ad43..cdd5e95a4e2 100644 --- a/src/mono/wasm/data/aot-tests/ProxyProjectForAOTOnHelix.proj +++ b/src/mono/wasm/data/aot-tests/ProxyProjectForAOTOnHelix.proj @@ -33,17 +33,15 @@ - - - - + <_ExtraFiles Include="$(ExtraFilesPath)**\*" /> - <_SatelliteAssembliesForVFS Include="@(WasmSatelliteAssemblies)" /> + <_SatelliteAssembliesForVFS Include="$(OriginalPublishDir)**\*.resources.dll" /> + <_SatelliteAssembliesForVFS CultureName="$([System.IO.Directory]::GetParent('%(Identity)').Name)" /> <_SatelliteAssembliesForVFS TargetPath="%(CultureName)\%(FileName)%(Extension)" /> diff --git a/src/tasks/WasmAppBuilder/WasmAppBuilder.cs b/src/tasks/WasmAppBuilder/WasmAppBuilder.cs index 49d984490a6..660272e268a 100644 --- a/src/tasks/WasmAppBuilder/WasmAppBuilder.cs +++ b/src/tasks/WasmAppBuilder/WasmAppBuilder.cs @@ -189,6 +189,13 @@ public override bool Execute () { string culture = assembly.GetMetadata("CultureName") ?? string.Empty; string fullPath = assembly.GetMetadata("Identity"); + if (string.IsNullOrEmpty(culture)) + { + Log.LogWarning($"Missing CultureName metadata for satellite assembly {fullPath}"); + continue; + } + // FIXME: validate the culture? + string name = Path.GetFileName(fullPath); string directory = Path.Combine(AppDir, config.AssemblyRoot, culture); Directory.CreateDirectory(directory); diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/BuildTestBase.cs b/src/tests/BuildWasmApps/Wasm.Build.Tests/BuildTestBase.cs index 99e721dfa65..b87ff5c70bf 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/BuildTestBase.cs +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/BuildTestBase.cs @@ -8,9 +8,11 @@ using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; +using System.Reflection; using System.Text; using Xunit; using Xunit.Abstractions; +using Xunit.Sdk; #nullable enable @@ -29,7 +31,6 @@ public abstract class BuildTestBase : IClassFixture test, string? buildDir=null, int expectedExitCode=0, string? args=null) + protected string RunAndTestWasmApp(BuildArgs buildArgs, + RunHost host, + string id, + Action? test=null, + string? buildDir = null, + int expectedExitCode = 0, + string? args = null, + Dictionary? envVars = null) { buildDir ??= _projectDir; - Dictionary? envVars = new(); + envVars ??= new(); envVars["XHARNESS_DISABLE_COLORED_OUTPUT"] = "true"; if (buildArgs.AOT) { @@ -180,6 +188,11 @@ protected void RunAndTestWasmApp(BuildArgs buildArgs, RunHost host, string id, A Assert.DoesNotContain("AOT: image 'System.Private.CoreLib' found.", output); Assert.DoesNotContain($"AOT: image '{buildArgs.ProjectName}' found.", output); } + + if (test != null) + test(output); + + return output; } protected static string RunWithXHarness(string testCommand, string testLogPath, string projectName, string bundleDir, @@ -209,6 +222,8 @@ protected void RunAndTestWasmApp(BuildArgs buildArgs, RunHost host, string id, A args.Append($" --run {projectName}.dll"); args.Append($" {appArgs ?? string.Empty}"); + _testOutput.WriteLine(string.Empty); + _testOutput.WriteLine($"---------- Running with {testCommand} ---------"); var (exitCode, output) = RunProcess("dotnet", _testOutput, args: args.ToString(), workingDir: bundleDir, @@ -251,14 +266,21 @@ protected static void InitProjectDir(string dir) runtime-test.js ##EXTRA_PROPERTIES## + + ##EXTRA_ITEMS## + + ##INSERT_AT_END## "; - protected static BuildArgs GetBuildArgsWith(BuildArgs buildArgs, string? extraProperties=null, string projectTemplate=SimpleProjectTemplate) + protected static BuildArgs ExpandBuildArgs(BuildArgs buildArgs, string extraProperties="", string extraItems="", string insertAtEnd="", string projectTemplate=SimpleProjectTemplate) { if (buildArgs.AOT) - extraProperties = $"{extraProperties}\ntrue\n"; + extraProperties = $"{extraProperties}\ntrue\nfalse\n"; - string projectContents = projectTemplate.Replace("##EXTRA_PROPERTIES##", extraProperties ?? string.Empty); + string projectContents = projectTemplate + .Replace("##EXTRA_PROPERTIES##", extraProperties) + .Replace("##EXTRA_ITEMS##", extraItems) + .Replace("##INSERT_AT_END##", insertAtEnd); return buildArgs with { ProjectFileContents = projectContents }; } @@ -273,10 +295,10 @@ protected static BuildArgs GetBuildArgsWith(BuildArgs buildArgs, string? extraPr { if (useCache && _buildContext.TryGetBuildFor(buildArgs, out BuildProduct? product)) { - Console.WriteLine ($"Using existing build found at {product.BuildPath}, with build log at {product.LogFile}"); + Console.WriteLine ($"Using existing build found at {product.ProjectDir}, with build log at {product.LogFile}"); - Assert.True(product.Result, $"Found existing build at {product.BuildPath}, but it had failed. Check build log at {product.LogFile}"); - _projectDir = product.BuildPath; + Assert.True(product.Result, $"Found existing build at {product.ProjectDir}, but it had failed. Check build log at {product.LogFile}"); + _projectDir = product.ProjectDir; // use this test's id for the run logs _logPath = Path.Combine(s_logRoot, id); @@ -297,7 +319,6 @@ protected static BuildArgs GetBuildArgsWith(BuildArgs buildArgs, string? extraPr throw new Exception("_projectDir should be set, to use createProject=false"); } - StringBuilder sb = new(); sb.Append("publish"); sb.Append(s_defaultBuildArgs); @@ -305,6 +326,7 @@ protected static BuildArgs GetBuildArgsWith(BuildArgs buildArgs, string? extraPr sb.Append($" /p:Configuration={buildArgs.Config}"); string logFilePath = Path.Combine(_logPath, $"{buildArgs.ProjectName}.binlog"); + _testOutput.WriteLine($"-------- Building ---------"); _testOutput.WriteLine($"Binlog path: {logFilePath}"); sb.Append($" /bl:\"{logFilePath}\" /v:minimal /nologo"); if (buildArgs.ExtraBuildArgs != null) @@ -378,8 +400,14 @@ protected static 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); + AssertNativeFile("dotnet.wasm"); + AssertNativeFile("dotnet.js"); + + void AssertNativeFile(string file) + => AssertFile(Path.Combine(nativeDir, file), + Path.Combine(bundleDir, file), + $"Expected {file} to be {(fromRuntimePack ? "the same as" : "different from")} the runtime pack", + same: fromRuntimePack); } protected static void AssertFilesDontExist(string dir, string[] filenames, string? label = null) @@ -464,6 +492,7 @@ protected static string GetRuntimeNativeDir() _testOutput.WriteLine($"Running {path} {args}"); Console.WriteLine($"Running: {path}: {args}"); Console.WriteLine($"WorkingDirectory: {workingDir}"); + _testOutput.WriteLine($"WorkingDirectory: {workingDir}"); StringBuilder outputBuilder = new (); var processStartInfo = new ProcessStartInfo { @@ -584,7 +613,7 @@ public static int Main() - + @@ -594,5 +623,5 @@ public static int Main() } public record BuildArgs(string ProjectName, string Config, bool AOT, string ProjectFileContents, string? ExtraBuildArgs); - public record BuildProduct(string BuildPath, string LogFile, bool Result); + public record BuildProduct(string ProjectDir, string LogFile, bool Result); } diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/InvariantGlobalizationTests.cs b/src/tests/BuildWasmApps/Wasm.Build.Tests/InvariantGlobalizationTests.cs index 6d01f20a842..753f8c40c2a 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/InvariantGlobalizationTests.cs +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/InvariantGlobalizationTests.cs @@ -49,7 +49,7 @@ public void RelinkingWithoutAOT(BuildArgs buildArgs, bool? invariantGlobalizatio extraProperties = $"{extraProperties}{invariantGlobalization}"; buildArgs = buildArgs with { ProjectName = projectName }; - buildArgs = GetBuildArgsWith(buildArgs, extraProperties); + buildArgs = ExpandBuildArgs(buildArgs, extraProperties); if (dotnetWasmFromRuntimePack == null) dotnetWasmFromRuntimePack = !(buildArgs.AOT || buildArgs.Config == "Release"); @@ -76,8 +76,8 @@ public static int Main() hasIcudt: invariantGlobalization == null || invariantGlobalization.Value == false); string expectedOutputString = invariantGlobalization == true - ? "False - en (ES)" - : "True - Invariant Language (Invariant Country)"; + ? "True - Invariant Language (Invariant Country)" + : "False - es (ES)"; RunAndTestWasmApp(buildArgs, expectedExitCode: 42, test: output => Assert.Contains(expectedOutputString, output), host: host, id: id); } diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/MainWithArgsTests.cs b/src/tests/BuildWasmApps/Wasm.Build.Tests/MainWithArgsTests.cs index df920577cea..b97a0490d2e 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/MainWithArgsTests.cs +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/MainWithArgsTests.cs @@ -77,7 +77,7 @@ public static int Main(string[] args) string programText = projectContents.Replace("##CODE##", code); buildArgs = buildArgs with { ProjectName = projectName, ProjectFileContents = programText }; - buildArgs = GetBuildArgsWith(buildArgs); + buildArgs = ExpandBuildArgs(buildArgs); if (dotnetWasmFromRuntimePack == null) dotnetWasmFromRuntimePack = !(buildArgs.AOT || buildArgs.Config == "Release"); diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/NativeBuildTests.cs b/src/tests/BuildWasmApps/Wasm.Build.Tests/NativeBuildTests.cs index da7b33d0a0c..9f87757175c 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/NativeBuildTests.cs +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/NativeBuildTests.cs @@ -39,7 +39,7 @@ public void Relinking_ErrorWhenMissingEMSDK(BuildArgs buildArgs, string emsdkPat ProjectName = projectName, ExtraBuildArgs = $"/p:EMSDK_PATH={emsdkPath}" }; - buildArgs = GetBuildArgsWith(buildArgs, extraProperties: "true"); + buildArgs = ExpandBuildArgs(buildArgs, extraProperties: "true"); (_, string buildOutput) = BuildProject(buildArgs, initProject: () => File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), s_mainReturns42), @@ -54,7 +54,7 @@ private void NativeBuild(string projectNamePrefix, string projectContents, Build string projectName = $"{projectNamePrefix}_{buildArgs.Config}_{buildArgs.AOT}"; buildArgs = buildArgs with { ProjectName = projectName, ProjectFileContents = projectContents }; - buildArgs = GetBuildArgsWith(buildArgs, extraProperties: "true"); + buildArgs = ExpandBuildArgs(buildArgs, extraProperties: "true"); Console.WriteLine ($"-- args: {buildArgs}, name: {projectName}"); BuildProject(buildArgs, diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/RebuildTests.cs b/src/tests/BuildWasmApps/Wasm.Build.Tests/RebuildTests.cs index aebaa43ba5d..ecbcbdd75c0 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/RebuildTests.cs +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/RebuildTests.cs @@ -27,7 +27,7 @@ public void NoOpRebuild(BuildArgs buildArgs, bool nativeRelink, RunHost host, st bool dotnetWasmFromRuntimePack = !nativeRelink && !buildArgs.AOT; buildArgs = buildArgs with { ProjectName = projectName }; - buildArgs = GetBuildArgsWith(buildArgs, $"{(nativeRelink ? "true" : "false")}"); + buildArgs = ExpandBuildArgs(buildArgs, $"{(nativeRelink ? "true" : "false")}"); BuildProject(buildArgs, initProject: () => File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), s_mainReturns42), diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/SatelliteAssembliesTests.cs b/src/tests/BuildWasmApps/Wasm.Build.Tests/SatelliteAssembliesTests.cs new file mode 100644 index 00000000000..e9d973650dc --- /dev/null +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/SatelliteAssembliesTests.cs @@ -0,0 +1,179 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Xunit; +using Xunit.Abstractions; + +#nullable enable + +namespace Wasm.Build.Tests +{ + public class SatelliteAssembliesTests : BuildTestBase + { + public SatelliteAssembliesTests(ITestOutputHelper output, SharedBuildPerTestClassFixture buildContext) + : base(output, buildContext) + { + } + + public static IEnumerable SatelliteAssemblyTestData(bool aot, bool relinking, RunHost host) + => ConfigWithAOTData(aot) + .Multiply( + new object?[] { relinking, "es-ES", "got: hola" }, + new object?[] { relinking, null, "got: hello" }, + new object?[] { relinking, "ja-JP", "got: \u3053\u3093\u306B\u3061\u306F" }) + .WithRunHosts(host) + .UnwrapItemsAsArrays(); + + [Theory] + [MemberData(nameof(SatelliteAssemblyTestData), parameters: new object[] { /*aot*/ false, /*relinking*/ false, RunHost.All })] + [MemberData(nameof(SatelliteAssemblyTestData), parameters: new object[] { /*aot*/ false, /*relinking*/ true, RunHost.All })] + [MemberData(nameof(SatelliteAssemblyTestData), parameters: new object[] { /*aot*/ true, /*relinking*/ false, RunHost.All })] + public void ResourcesFromMainAssembly(BuildArgs buildArgs, + bool nativeRelink, + string? argCulture, + string expectedOutput, + RunHost host, + string id) + { + string projectName = $"sat_asm_from_main_asm"; + bool dotnetWasmFromRuntimePack = !nativeRelink && !buildArgs.AOT; + + buildArgs = buildArgs with { ProjectName = projectName }; + buildArgs = ExpandBuildArgs(buildArgs, + projectTemplate: s_resourcesProjectTemplate, + extraProperties: $"{(nativeRelink ? "true" : "false")}", + extraItems: $""); + + BuildProject(buildArgs, + initProject: () => CreateProgramForCultureTest($"{projectName}.words", "TestClass"), + dotnetWasmFromRuntimePack: dotnetWasmFromRuntimePack, + id: id); + + string output = RunAndTestWasmApp( + buildArgs, expectedExitCode: 42, + args: argCulture, + host: host, id: id); + + Assert.Contains(expectedOutput, output); + } + + [Theory] + [MemberData(nameof(SatelliteAssemblyTestData), parameters: new object[] { /*aot*/ false, /*relinking*/ false, RunHost.All })] + [MemberData(nameof(SatelliteAssemblyTestData), parameters: new object[] { /*aot*/ false, /*relinking*/ true, RunHost.All })] + [MemberData(nameof(SatelliteAssemblyTestData), parameters: new object[] { /*aot*/ true, /*relinking*/ false, RunHost.All })] + public void ResourcesFromProjectReference(BuildArgs buildArgs, + bool nativeRelink, + string? argCulture, + string expectedOutput, + RunHost host, + string id) + { + string projectName = $"sat_asm_proj_ref"; + bool dotnetWasmFromRuntimePack = !nativeRelink && !buildArgs.AOT; + + buildArgs = buildArgs with { ProjectName = projectName }; + buildArgs = ExpandBuildArgs(buildArgs, + projectTemplate: s_resourcesProjectTemplate, + extraProperties: $"{(nativeRelink ? "true" : "false")}", + extraItems: $""); + + BuildProject(buildArgs, + initProject: () => CreateProgramForCultureTest("LibraryWithResources.words", "LibraryWithResources.Class1"), + dotnetWasmFromRuntimePack: dotnetWasmFromRuntimePack, + id: id); + + string output = RunAndTestWasmApp(buildArgs, + expectedExitCode: 42, + args: argCulture, + host: host, id: id); + + Assert.Contains(expectedOutput, output); + } + +#pragma warning disable xUnit1026 + [Theory] + [BuildAndRun(host: RunHost.None, aot: true)] + public void CheckThatSatelliteAssembliesAreNotAOTed(BuildArgs buildArgs, string id) + { + string projectName = $"check_sat_asm_not_aot"; + buildArgs = buildArgs with { ProjectName = projectName }; + buildArgs = ExpandBuildArgs(buildArgs, + projectTemplate: s_resourcesProjectTemplate, + extraProperties: $@" + -O0 + -O0", + extraItems: $""); + + System.Console.WriteLine ($"--- aot: {buildArgs.AOT}"); + BuildProject(buildArgs, + initProject: () => CreateProgramForCultureTest($"{projectName}.words", "TestClass"), + dotnetWasmFromRuntimePack: false, + id: id); + + var bitCodeFileNames = Directory.GetFileSystemEntries(Path.Combine(_projectDir!, "obj"), "*.dll.bc", SearchOption.AllDirectories) + .Select(path => Path.GetFileName(path)) + .ToArray(); + + // sanity check, in case we change file extensions + Assert.Contains($"{projectName}.dll.bc", bitCodeFileNames); + + Assert.Empty(bitCodeFileNames.Where(file => file.EndsWith(".resources.dll.bc"))); + } +#pragma warning restore xUnit1026 + + private void CreateProgramForCultureTest(string resourceName, string typeName) + => File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), + s_cultureResourceTestProgram + .Replace("##RESOURCE_NAME##", resourceName) + .Replace("##TYPE_NAME##", typeName)); + + private const string s_resourcesProjectTemplate = + @$" + + {s_targetFramework} + Exe + true + runtime-test.js + ##EXTRA_PROPERTIES## + + + ##EXTRA_ITEMS## + + ##INSERT_AT_END## + "; + + private static string s_cultureResourceTestProgram = @" +using System; +using System.Runtime.CompilerServices; +using System.Globalization; +using System.Resources; +using System.Threading; + +namespace ResourcesTest +{ + public class TestClass + { + public static int Main(string[] args) + { + if (args.Length == 1) + { + string cultureToTest = args[0]; + var newCulture = new CultureInfo(cultureToTest); + Thread.CurrentThread.CurrentCulture = newCulture; + Thread.CurrentThread.CurrentUICulture = newCulture; + } + + var currentCultureName = Thread.CurrentThread.CurrentCulture.Name; + + var rm = new ResourceManager(""##RESOURCE_NAME##"", typeof(##TYPE_NAME##).Assembly); + Console.WriteLine($""For '{currentCultureName}' got: {rm.GetString(""hello"")}""); + + return 42; + } + } +}"; + } +} diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/SharedBuildPerTestClassFixture.cs b/src/tests/BuildWasmApps/Wasm.Build.Tests/SharedBuildPerTestClassFixture.cs index a491d972af2..e84a151bd5b 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/SharedBuildPerTestClassFixture.cs +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/SharedBuildPerTestClassFixture.cs @@ -20,7 +20,7 @@ public void CacheBuild(BuildArgs buildArgs, BuildProduct product) public void RemoveFromCache(string buildPath) { - KeyValuePair? foundKvp = _buildPaths.Where(kvp => kvp.Value.BuildPath == buildPath).SingleOrDefault(); + KeyValuePair? foundKvp = _buildPaths.Where(kvp => kvp.Value.ProjectDir == buildPath).SingleOrDefault(); if (foundKvp == null) throw new Exception($"Could not find build path {buildPath} in cache to remove."); @@ -36,7 +36,7 @@ public void Dispose() Console.WriteLine ($"============== DELETING THE BUILDS ============="); foreach (var kvp in _buildPaths.Values) { - RemoveDirectory(kvp.BuildPath); + RemoveDirectory(kvp.ProjectDir); } } 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 9ed56506d79..20a19724307 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/Wasm.Build.Tests.csproj +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/Wasm.Build.Tests.csproj @@ -9,6 +9,7 @@ xunit false true + false TEST_DEBUG_CONFIG_ALSO false @@ -20,8 +21,6 @@ <_PreCommand Condition="'$(OS)' != 'Windows_NT'">WasmBuildSupportDir=%24{HELIX_CORRELATION_PAYLOAD}/build <_PreCommand Condition="'$(OS)' == 'Windows_NT'">set WasmBuildSupportDir=%HELIX_CORRELATION_PAYLOAD%/build & - <_PreCommand Condition="'$(OS)' != 'Windows_NT'">$(_PreCommand) DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1 - <_PreCommand Condition="'$(OS)' == 'Windows_NT'">$(_PreCommand) set DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1 & @@ -38,5 +37,7 @@ + + diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/WasmBuildAppTest.cs b/src/tests/BuildWasmApps/Wasm.Build.Tests/WasmBuildAppTest.cs index 3778d1fcdaa..e426c9523d9 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/WasmBuildAppTest.cs +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/WasmBuildAppTest.cs @@ -72,7 +72,7 @@ public void AOT_ErrorWhenMissingEMSDK(BuildArgs buildArgs, string emsdkPath, str ProjectName = projectName, ExtraBuildArgs = $"/p:EMSDK_PATH={emsdkPath}" }; - buildArgs = GetBuildArgsWith(buildArgs); + buildArgs = ExpandBuildArgs(buildArgs); (_, string buildOutput) = BuildProject(buildArgs, initProject: () => File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), s_mainReturns42), @@ -88,6 +88,9 @@ public class TestClass { public static int Main() { Console.WriteLine($""tc: {Environment.TickCount}, tc64: {Environment.TickCount64}""); + + // if this gets printed, then we didn't crash! + Console.WriteLine(""Hello, World!""); return 42; } }"; @@ -109,11 +112,11 @@ public void Bug49588_RegressionTest_NativeRelinking(BuildArgs buildArgs, RunHost BuildArgs buildArgs, RunHost host, string id, - string? extraProperties = null, + string extraProperties = "", bool? dotnetWasmFromRuntimePack = null) { buildArgs = buildArgs with { ProjectName = projectName }; - buildArgs = GetBuildArgsWith(buildArgs, extraProperties); + buildArgs = ExpandBuildArgs(buildArgs, extraProperties); if (dotnetWasmFromRuntimePack == null) dotnetWasmFromRuntimePack = !(buildArgs.AOT || buildArgs.Config == "Release"); diff --git a/src/tests/BuildWasmApps/testassets/LibraryWithResources/Class1.cs b/src/tests/BuildWasmApps/testassets/LibraryWithResources/Class1.cs new file mode 100644 index 00000000000..4674bfd7d0b --- /dev/null +++ b/src/tests/BuildWasmApps/testassets/LibraryWithResources/Class1.cs @@ -0,0 +1,11 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; + +namespace LibraryWithResources +{ + public class Class1 + { + } +} diff --git a/src/tests/BuildWasmApps/testassets/LibraryWithResources/Directory.Build.props b/src/tests/BuildWasmApps/testassets/LibraryWithResources/Directory.Build.props new file mode 100644 index 00000000000..058246e4086 --- /dev/null +++ b/src/tests/BuildWasmApps/testassets/LibraryWithResources/Directory.Build.props @@ -0,0 +1 @@ + diff --git a/src/tests/BuildWasmApps/testassets/LibraryWithResources/Directory.Build.targets b/src/tests/BuildWasmApps/testassets/LibraryWithResources/Directory.Build.targets new file mode 100644 index 00000000000..058246e4086 --- /dev/null +++ b/src/tests/BuildWasmApps/testassets/LibraryWithResources/Directory.Build.targets @@ -0,0 +1 @@ + diff --git a/src/tests/BuildWasmApps/testassets/LibraryWithResources/LibraryWithResources.csproj b/src/tests/BuildWasmApps/testassets/LibraryWithResources/LibraryWithResources.csproj new file mode 100644 index 00000000000..91961dd7d6b --- /dev/null +++ b/src/tests/BuildWasmApps/testassets/LibraryWithResources/LibraryWithResources.csproj @@ -0,0 +1,10 @@ + + + + net5.0 + + + + + + diff --git a/src/tests/BuildWasmApps/testassets/resx/words.es-ES.resx b/src/tests/BuildWasmApps/testassets/resx/words.es-ES.resx new file mode 100644 index 00000000000..775397b15a2 --- /dev/null +++ b/src/tests/BuildWasmApps/testassets/resx/words.es-ES.resx @@ -0,0 +1,127 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + ciao + + + + hola + + diff --git a/src/tests/BuildWasmApps/testassets/resx/words.ja-JP.resx b/src/tests/BuildWasmApps/testassets/resx/words.ja-JP.resx new file mode 100644 index 00000000000..c843811244c --- /dev/null +++ b/src/tests/BuildWasmApps/testassets/resx/words.ja-JP.resx @@ -0,0 +1,127 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + さようなら + + + + こんにちは + + diff --git a/src/tests/BuildWasmApps/testassets/resx/words.resx b/src/tests/BuildWasmApps/testassets/resx/words.resx new file mode 100644 index 00000000000..c3d5a787420 --- /dev/null +++ b/src/tests/BuildWasmApps/testassets/resx/words.resx @@ -0,0 +1,127 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + bye + + + + hello + + -- GitLab