-
Notifications
You must be signed in to change notification settings - Fork 944
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Unit tests fail on macOS (and probably on Linux too) #1021
Comments
Here's the small program I wrote to diagnose the assignculture.csproj <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="NSubstitute" Version="4.2.2" />
<PackageReference Include="ReflectionMagic" Version="4.1.0" />
</ItemGroup>
<ItemGroup Condition="'$(ReferenceMsBuildNuGetPackages)' != 'true'">
<Reference Include="/usr/local/share/dotnet/sdk/5.0.101/Microsoft.Build.Framework.dll" />
<Reference Include="/usr/local/share/dotnet/sdk/5.0.101/Microsoft.Build.Tasks.Core.dll" />
<Reference Include="/usr/local/share/dotnet/sdk/5.0.101/Microsoft.Build.Utilities.Core.dll" />
</ItemGroup>
<ItemGroup Condition="'$(ReferenceMsBuildNuGetPackages)' == 'true'">
<PackageReference Include="Microsoft.Build.Tasks.Core" Version="16.8.0" />
</ItemGroup>
</Project> Program.cs using System;
using System.Globalization;
using System.Linq;
using System.Runtime.InteropServices;
using Microsoft.Build.Framework;
using Microsoft.Build.Tasks;
using Microsoft.Build.Utilities;
using NSubstitute;
using ReflectionMagic;
try
{
SimulateMsBuildInitialization();
PrintAllChineseCultures();
var task = RunAssignCultureTask("Resources.zh-CN.resx", "Resources.zh-Hans.resx");
PrintAssignedFiles(task);
}
catch (Exception exception)
{
Console.Error.WriteLine(exception);
}
static void SimulateMsBuildInitialization()
{
var assembly = typeof(AssignCulture).Assembly;
assembly.GetType("Microsoft.Build.Shared.AssemblyUtilities", throwOnError: true).AsDynamicType().Initialize();
Console.WriteLine($"Running on {RuntimeInformation.FrameworkDescription} using {assembly} at {assembly.Location}");
Console.WriteLine();
}
static void PrintAllChineseCultures()
{
Console.WriteLine("*** All Chinese cultures ***");
foreach (var culture in CultureInfo.GetCultures(CultureTypes.AllCultures).Where(e => e.Name.StartsWith("zh")))
{
Console.WriteLine($"[{culture.Name}] {culture.EnglishName}");
}
Console.WriteLine();
}
static AssignCulture RunAssignCultureTask(params string[] cultureNames)
{
var buildEngine = Substitute.For<IBuildEngine>();
buildEngine.LogMessageEvent(Arg.Do<BuildMessageEventArgs>(e => Console.WriteLine($"[{e.Importance}] {e.Message}")));
var task = new AssignCulture
{
BuildEngine = buildEngine,
Files = cultureNames.Select(e => new TaskItem(e)).Cast<ITaskItem>().ToArray(),
};
task.Execute();
Console.WriteLine();
return task;
}
static void PrintAssignedFiles(AssignCulture task)
{
PrintTaskItems(task.AssignedFilesWithNoCulture, nameof(task.AssignedFilesWithNoCulture));
PrintTaskItems(task.AssignedFilesWithCulture, nameof(task.AssignedFilesWithCulture));
}
static void PrintTaskItems(ITaskItem[] taskItems, string name)
{
var itemSpecModifiers = typeof(AssignCulture).Assembly.GetType("Microsoft.Build.Shared.FileUtilities+ItemSpecModifiers", throwOnError: true).AsDynamicType();
Console.WriteLine($"{name}: {taskItems.Length}");
foreach (var taskItem in taskItems)
{
Console.WriteLine($" {taskItem.ItemSpec}");
foreach (var metadataName in taskItem.MetadataNames.Cast<string>().Where(e => !itemSpecModifiers.IsItemSpecModifier(e)))
{
var metadata = taskItem.GetMetadata(metadataName);
if (!string.IsNullOrEmpty(metadata))
{
Console.WriteLine($" {metadataName} = {metadata}");
}
}
}
} Here's the output when run with
And here's the result when running on Windows with
The difference, as we can see, is that I'm not sure yet what is the best solution to this problem. |
The `Initialize()` method must be called before testing the `s_cultureInfoGetCultureMethod` static field. This might go unnoticed if the `Initialize` method was called earlier through some other code path but the result of calling `CultureInfoHasGetCultures()` would be wrong if `Initialize()` was not called beforehand. For example, in the static constructor of `Microsoft.Build.Tasks.CultureInfoCache`. Note: I stumbled on this when [diagnosing an issue][1] with the AssignCulture task. [1]: Humanizr/Humanizer#1021 (comment)
Well, it turns out I just re-discovered a known MSBuild issue apparently: dotnet/msbuild#3897 |
Here is how to reproduce:
I have noticed that the
zh-CN
resources are not copied intosrc/Humanizer.Tests/bin/Debug/netcoreapp2.1
. All other localizations are there (af
,ar
, ...fr
,fr-BE
, ...,zh-Hans
,zh-Hant
) but there is nozh-CN
directory containing aHumanizer.resources.dll
file.So I ran
dotnet build -bl
and examined the binary log with MSBuild Structured Log Viewer. It turns out that theAssignCulture
task (which is run by theSplitResourcesByCulture
target) miscategorizes thezh-CN
culture which ends up in theResxWithNoCulture
item group instead of theResxWithCulture
item group where all other localized resources are.I'm currently investigating why the AssignCulture task does not recognize
zh-CN
as a valid culture on macOS.The text was updated successfully, but these errors were encountered: