Skip to content
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

[Blazor] Add basic ICU tests #89771

Merged
merged 22 commits into from
Aug 9, 2023
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions eng/testing/scenarios/BuildWasmAppsJobsList.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,13 @@ Wasm.Build.Tests.Blazor.MiscTests
Wasm.Build.Tests.Blazor.MiscTests2
Wasm.Build.Tests.Blazor.NativeTests
Wasm.Build.Tests.Blazor.NoopNativeRebuildTest
Wasm.Build.Tests.Blazor.IcuTests
Wasm.Build.Tests.BuildPublishTests
Wasm.Build.Tests.ConfigSrcTests
Wasm.Build.Tests.HybridGlobalizationTests
Wasm.Build.Tests.IcuShardingTests
Wasm.Build.Tests.IcuShardingTests2
Wasm.Build.Tests.IcuTests
Wasm.Build.Tests.InvariantGlobalizationTests
Wasm.Build.Tests.InvariantTimezoneTests
Wasm.Build.Tests.MainWithArgsTests
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,15 +163,17 @@ Copyright (c) .NET Foundation. All rights reserved.
<Target Name="_ResolveGlobalizationConfiguration">
<Error Condition="'$(BlazorIcuDataFileName)' != '' AND !$([System.IO.Path]::GetFileName('$(BlazorIcuDataFileName)').StartsWith('icudt'))" Text="File name in %24(BlazorIcuDataFileName) has to start with 'icudt'." />
<Warning Condition="'$(InvariantGlobalization)' == 'true' AND '$(BlazorWebAssemblyLoadAllGlobalizationData)' == 'true'" Text="%24(BlazorWebAssemblyLoadAllGlobalizationData) has no effect when %24(InvariantGlobalization) is set to true." />
<Warning Condition="'$(HybridGlobalization)' == 'true' AND '$(BlazorWebAssemblyLoadAllGlobalizationData)' == 'true'" Text="%24(BlazorWebAssemblyLoadAllGlobalizationData) has no effect when %24(HybridGlobalization) is set to true." />
<Warning Condition="'$(InvariantGlobalization)' == 'true' AND '$(BlazorIcuDataFileName)' != ''" Text="%24(BlazorIcuDataFileName) has no effect when %24(InvariantGlobalization) is set to true." />
<Warning Condition="'$(BlazorWebAssemblyLoadAllGlobalizationData)' == 'true' AND '$(BlazorIcuDataFileName)' != ''" Text="%24(BlazorIcuDataFileName) has no effect when %24(BlazorWebAssemblyLoadAllGlobalizationData) is set to true." />
<Warning Condition="'$(InvariantGlobalization)' == 'true' AND '$(HybridGlobalization)' == 'true'" Text="%24(HybridGlobalization) has no effect when %24(InvariantGlobalization) is set to true." />
<Warning Condition="'$(BlazorIcuDataFileName)' != '' AND '$(HybridGlobalization)' == 'true'" Text="%24(HybridGlobalization) has no effect when %24(BlazorIcuDataFileName) is set." />
<PropertyGroup>
<HybridGlobalization Condition="'$(BlazorIcuDataFileName)' != ''">false</HybridGlobalization>
<_BlazorWebAssemblyLoadAllGlobalizationData Condition="'$(InvariantGlobalization)' != 'true'">$(BlazorWebAssemblyLoadAllGlobalizationData)</_BlazorWebAssemblyLoadAllGlobalizationData>
<_BlazorWebAssemblyLoadAllGlobalizationData Condition="'$(InvariantGlobalization)' != 'true' AND '$(HybridGlobalization)' != 'true'">$(BlazorWebAssemblyLoadAllGlobalizationData)</_BlazorWebAssemblyLoadAllGlobalizationData>
<_BlazorWebAssemblyLoadAllGlobalizationData Condition="'$(_BlazorWebAssemblyLoadAllGlobalizationData)' == ''">false</_BlazorWebAssemblyLoadAllGlobalizationData>
<_IsHybridGlobalization Condition="'$(InvariantGlobalization)' != 'true' AND '$(HybridGlobalization)' == 'true'"></_IsHybridGlobalization>
<_IsHybridGlobalization>$(HybridGlobalization)</_IsHybridGlobalization>
<_IsHybridGlobalization Condition="'$(InvariantGlobalization)' == 'true' OR '$(HybridGlobalization)' == ''">false</_IsHybridGlobalization>
<_BlazorIcuDataFileName Condition="'$(InvariantGlobalization)' != 'true' AND '$(BlazorWebAssemblyLoadAllGlobalizationData)' != 'true' AND '$(HybridGlobalization)' != 'true'">$(BlazorIcuDataFileName)</_BlazorIcuDataFileName>
<_LoadCustomIcuData>false</_LoadCustomIcuData>
<_LoadCustomIcuData Condition="'$(_BlazorIcuDataFileName)' != ''">true</_LoadCustomIcuData>
Expand Down Expand Up @@ -240,6 +242,8 @@ Copyright (c) .NET Foundation. All rights reserved.
ProjectSatelliteAssemblies="@(IntermediateSatelliteAssembliesWithTargetPath)"
TimeZoneSupport="$(_BlazorEnableTimeZoneSupport)"
InvariantGlobalization="$(_WasmInvariantGlobalization)"
HybridGlobalization="$(_IsHybridGlobalization)"
LoadFullICUData="$(_BlazorWebAssemblyLoadAllGlobalizationData)"
DotNetJsVersion="$(_WasmRuntimePackVersion)"
CopySymbols="$(_WasmCopyOutputSymbolsToOutputDirectory)"
OutputPath="$(OutputPath)"
Expand Down Expand Up @@ -366,7 +370,7 @@ Copyright (c) .NET Foundation. All rights reserved.
InvariantGlobalization="$(InvariantGlobalization)"
LoadCustomIcuData="$(_LoadCustomIcuData)"
IsHybridGlobalization="$(_IsHybridGlobalization)"
LoadAllICUData="$(_BlazorWebAssemblyLoadAllGlobalizationData)"
LoadFullICUData="$(_BlazorWebAssemblyLoadAllGlobalizationData)"
StartupMemoryCache="$(_BlazorWebAssemblyStartupMemoryCache)"
Jiterpreter="$(_BlazorWebAssemblyJiterpreter)"
RuntimeOptions="$(_BlazorWebAssemblyRuntimeOptions)"
Expand Down Expand Up @@ -414,6 +418,8 @@ Copyright (c) .NET Foundation. All rights reserved.
PublishPath="$(PublishDir)"
WasmAotAssets="@(WasmNativeAsset)"
InvariantGlobalization="$(_WasmInvariantGlobalization)"
HybridGlobalization="$(_IsHybridGlobalization)"
LoadFullICUData="$(_BlazorWebAssemblyLoadAllGlobalizationData)"
CopySymbols="$(CopyOutputSymbolsToPublishDirectory)"
ExistingAssets="@(_WasmPublishPrefilteredAssets)"
DotNetJsVersion="$(_WasmRuntimePackVersion)"
Expand Down Expand Up @@ -557,7 +563,7 @@ Copyright (c) .NET Foundation. All rights reserved.
InvariantGlobalization="$(InvariantGlobalization)"
LoadCustomIcuData="$(_LoadCustomIcuData)"
IsHybridGlobalization="$(_IsHybridGlobalization)"
LoadAllICUData="$(_BlazorWebAssemblyLoadAllGlobalizationData)"
LoadFullICUData="$(_BlazorWebAssemblyLoadAllGlobalizationData)"
StartupMemoryCache="$(_BlazorWebAssemblyStartupMemoryCache)"
Jiterpreter="$(_BlazorWebAssemblyJiterpreter)"
RuntimeOptions="$(_BlazorWebAssemblyRuntimeOptions)"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,7 @@ public record BlazorBuildOptions
bool WarnAsError = true,
bool ExpectRelinkDirWhenPublishing = false,
bool ExpectFingerprintOnDotnetJs = false,
RuntimeVariant RuntimeType = RuntimeVariant.SingleThreaded
RuntimeVariant RuntimeType = RuntimeVariant.SingleThreaded,
GlobalizationMode GlobalizationMode = GlobalizationMode.Sharded,
string PredefinedIcudt = ""
);
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@ public void AssertBundle(BlazorBuildOptions options)
IsPublish: options.IsPublish,
TargetFramework: options.TargetFramework,
BinFrameworkDir: FindBinFrameworkDir(options.Config, options.IsPublish, options.TargetFramework),
GlobalizationMode: GlobalizationMode.Sharded,
PredefinedIcudt: null,
GlobalizationMode: options.GlobalizationMode,
PredefinedIcudt: options.PredefinedIcudt,
ExpectFingerprintOnDotnetJs: options.ExpectFingerprintOnDotnetJs,
ExpectedFileType: options.ExpectedFileType,
RuntimeType: options.RuntimeType,
AssertIcuAssets: false, // FIXME: this is broken right now
AssertIcuAssets: true,
AssertSymbolsFile: false // FIXME: not supported yet
));
}
2 changes: 2 additions & 0 deletions src/mono/wasm/Wasm.Build.Tests/Blazor/BlazorWasmTestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -216,4 +216,6 @@ void OnErrorMessage(string msg)

public string FindBlazorBinFrameworkDir(string config, bool forPublish, string framework = DefaultTargetFrameworkForBlazor)
=> _provider.FindBinFrameworkDir(config: config, forPublish: forPublish, framework: framework);

public string GetRandomNameWithoutDots() => Path.GetRandomFileName().Replace(".", "");
}
98 changes: 98 additions & 0 deletions src/mono/wasm/Wasm.Build.Tests/Blazor/IcuTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
// 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.IO;
using Xunit;
using Xunit.Abstractions;
using Xunit.Sdk;
using System.Collections.Generic;

#nullable enable

namespace Wasm.Build.Tests.Blazor;

// these tests only check if correct ICU files got copied
public class IcuTests : BlazorWasmTestBase
ilonatommy marked this conversation as resolved.
Show resolved Hide resolved
{
public IcuTests(ITestOutputHelper output, SharedBuildPerTestClassFixture buildContext)
: base(output, buildContext) {}

string getRandomNameWithoutDots => Path.GetRandomFileName().Replace(".", "");
ilonatommy marked this conversation as resolved.
Show resolved Hide resolved

[Theory]
[InlineData("Debug", false)]
[InlineData("Debug", true)]
[InlineData("Release", false)]
[InlineData("Release", true)]
public void HybridWithInvariant(string config, bool invariant)
{
string id = $"blz_hybrid_{config}_{getRandomNameWithoutDots}";
string projectFile = CreateProjectWithNativeReference(id);
ilonatommy marked this conversation as resolved.
Show resolved Hide resolved
AddItemsPropertiesToProject(
projectFile,
extraProperties:
$"<HybridGlobalization>true</HybridGlobalization><InvariantGlobalization>{invariant}</InvariantGlobalization>");

(CommandResult res, string logPath) = BlazorBuild(
new BlazorBuildOptions(
id,
config,
WarnAsError: false,
radical marked this conversation as resolved.
Show resolved Hide resolved
GlobalizationMode: invariant ? GlobalizationMode.Invariant : GlobalizationMode.Hybrid,
ExpectedFileType: NativeFilesType.Relinked
));
if (invariant)
Assert.Contains("$(HybridGlobalization) has no effect when $(InvariantGlobalization) is set to true.", res.Output);
ilonatommy marked this conversation as resolved.
Show resolved Hide resolved
}

[Theory]
[InlineData("Debug", false)]
[InlineData("Debug", true)]
[InlineData("Release", false)]
[InlineData("Release", true)]
ilonatommy marked this conversation as resolved.
Show resolved Hide resolved
public void HybridWithFullIcuFromRuntimePack(string config, bool fullIcu)
{
string id = $"blz_hybrid_{config}_{getRandomNameWithoutDots}";
string projectFile = CreateProjectWithNativeReference(id);
AddItemsPropertiesToProject(projectFile, extraProperties:
$"<HybridGlobalization>true</HybridGlobalization><BlazorWebAssemblyLoadAllGlobalizationData>{fullIcu}</BlazorWebAssemblyLoadAllGlobalizationData>");

(CommandResult res, string logPath) = BlazorBuild(
new BlazorBuildOptions(
id,
config,
WarnAsError: false,
GlobalizationMode: GlobalizationMode.Hybrid,
ExpectedFileType: NativeFilesType.Relinked
));
if (fullIcu)
Assert.Contains("$(BlazorWebAssemblyLoadAllGlobalizationData) has no effect when $(HybridGlobalization) is set to true.", res.Output);
}


ilonatommy marked this conversation as resolved.
Show resolved Hide resolved
[Theory]
[InlineData("Debug", false)]
[InlineData("Debug", true)]
[InlineData("Release", false)]
[InlineData("Release", true)]
public void FullIcuFromRuntimePackWithInvariant(string config, bool invariant)
{
string id = $"blz_hybrid_{config}_{getRandomNameWithoutDots}";
string projectFile = CreateProjectWithNativeReference(id);
AddItemsPropertiesToProject(projectFile, extraProperties:
$"<BlazorWebAssemblyLoadAllGlobalizationData>true</BlazorWebAssemblyLoadAllGlobalizationData><InvariantGlobalization>{invariant}</InvariantGlobalization>");

(CommandResult res, string logPath) = BlazorBuild(
new BlazorBuildOptions(
id,
config,
WarnAsError: false,
GlobalizationMode: invariant ? GlobalizationMode.Invariant : GlobalizationMode.FullIcu,
ExpectedFileType: NativeFilesType.Relinked
));

if (invariant)
Assert.Contains("$(BlazorWebAssemblyLoadAllGlobalizationData) has no effect when $(InvariantGlobalization) is set to true.", res.Output);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@ public enum GlobalizationMode
Sharded, // chosen based on locale
Invariant, // no icu
FullIcu, // full icu data: icudt.dat is loaded
PredefinedIcu, // user set WasmIcuDataFileName value and we are loading that file
PredefinedIcu, // user set WasmIcuDataFileName/BlazorIcuDataFileName value and we are loading that file
Hybrid // reduced icu, missing data is provided by platform-native functions (web api for wasm)
};
19 changes: 19 additions & 0 deletions src/mono/wasm/Wasm.Build.Tests/Common/IcuTestsHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// 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.IO;
using Xunit;
using Xunit.Abstractions;
using Xunit.Sdk;
using System.Collections.Generic;

#nullable enable

namespace Wasm.Build.Tests;

public static class IcuTestsHelper
{
// custom file contains only locales "cy-GB", "is-IS", "bs-BA", "lb-LU" and fallback locale: "en-US":
public static string CustomIcuPath = Path.Combine(BuildEnvironment.TestAssetsPath, "icudt_custom.dat");
}
63 changes: 63 additions & 0 deletions src/mono/wasm/Wasm.Build.Tests/IcuShardingTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// 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.IO;
using Xunit;
using Xunit.Abstractions;
using Xunit.Sdk;
using System.Collections.Generic;

#nullable enable

namespace Wasm.Build.Tests;

public class IcuShardingTests : IcuTestsBase
{
public IcuShardingTests(ITestOutputHelper output, SharedBuildPerTestClassFixture buildContext)
: base(output, buildContext) { }

public static IEnumerable<object?[]> IcuExpectedAndMissingCustomShardTestData(bool aot, RunHost host)
=> ConfigWithAOTData(aot)
.Multiply(
new object[] { IcuTestsHelper.CustomIcuPath, CustomIcuTestedLocales, false },
new object[] { IcuTestsHelper.CustomIcuPath, CustomIcuTestedLocales, true })
.WithRunHosts(host)
.UnwrapItemsAsArrays();

public static IEnumerable<object?[]> IcuExpectedAndMissingAutomaticShardTestData(bool aot)
=> ConfigWithAOTData(aot)
.Multiply(
new object[] { "fr-FR", GetEfigsTestedLocales(SundayNames.French)},
new object[] { "ja-JP", GetCjkTestedLocales(SundayNames.Japanese) },
new object[] { "sk-SK", GetNocjkTestedLocales(SundayNames.Slovak) })
.WithRunHosts(BuildTestBase.s_hostsForOSLocaleSensitiveTests)
.UnwrapItemsAsArrays();

[Theory]
[MemberData(nameof(IcuExpectedAndMissingCustomShardTestData), parameters: new object[] { false, RunHost.NodeJS | RunHost.Chrome })]
[MemberData(nameof(IcuExpectedAndMissingCustomShardTestData), parameters: new object[] { true, RunHost.NodeJS | RunHost.Chrome })]
public void CustomIcuShard(BuildArgs buildArgs, string shardName, string testedLocales, bool onlyPredefinedCultures, RunHost host, string id) =>
TestIcuShards(buildArgs, shardName, testedLocales, host, id, onlyPredefinedCultures);

[Theory]
[MemberData(nameof(IcuExpectedAndMissingAutomaticShardTestData), parameters: new object[] { false })]
[MemberData(nameof(IcuExpectedAndMissingAutomaticShardTestData), parameters: new object[] { true })]
public void AutomaticShardSelectionDependingOnEnvLocale(BuildArgs buildArgs, string environmentLocale, string testedLocales, RunHost host, string id)
{
string projectName = $"automatic_shard_{environmentLocale}_{buildArgs.Config}_{buildArgs.AOT}";
bool dotnetWasmFromRuntimePack = !(buildArgs.AOT || buildArgs.Config == "Release");

buildArgs = buildArgs with { ProjectName = projectName };
buildArgs = ExpandBuildArgs(buildArgs);

string programText = GetProgramText(testedLocales);
_testOutput.WriteLine($"----- Program: -----{Environment.NewLine}{programText}{Environment.NewLine}-------");
(_, string output) = BuildProject(buildArgs,
id: id,
new BuildProjectOptions(
InitProject: () => File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), programText),
DotnetWasmFromRuntimePack: dotnetWasmFromRuntimePack));
string runOutput = RunAndTestWasmApp(buildArgs, buildDir: _projectDir, expectedExitCode: 42, host: host, id: id, environmentLocale: environmentLocale);
}
}
39 changes: 39 additions & 0 deletions src/mono/wasm/Wasm.Build.Tests/IcuShardingTests2.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// 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.IO;
using Xunit;
using Xunit.Abstractions;
using Xunit.Sdk;
using System.Collections.Generic;

#nullable enable

namespace Wasm.Build.Tests;

public class IcuShardingTests2 : IcuTestsBase
{
public IcuShardingTests2(ITestOutputHelper output, SharedBuildPerTestClassFixture buildContext)
: base(output, buildContext) { }

public static IEnumerable<object?[]> IcuExpectedAndMissingShardFromRuntimePackTestData(bool aot, RunHost host)
=> ConfigWithAOTData(aot)
.Multiply(
new object[] { "icudt.dat",
$@"new Locale[] {{
new Locale(""en-GB"", ""{SundayNames.English}""), new Locale(""zh-CN"", ""{SundayNames.Chinese}""), new Locale(""sk-SK"", ""{SundayNames.Slovak}""),
new Locale(""xx-yy"", null) }}" },
new object[] { "icudt_EFIGS.dat", GetEfigsTestedLocales() },
new object[] { "icudt_CJK.dat", GetCjkTestedLocales() },
new object[] { "icudt_no_CJK.dat", GetNocjkTestedLocales() })
.WithRunHosts(host)
.UnwrapItemsAsArrays();


[Theory]
[MemberData(nameof(IcuExpectedAndMissingShardFromRuntimePackTestData), parameters: new object[] { false, RunHost.NodeJS | RunHost.Chrome })]
[MemberData(nameof(IcuExpectedAndMissingShardFromRuntimePackTestData), parameters: new object[] { true, RunHost.NodeJS | RunHost.Chrome })]
public void DefaultAvailableIcuShardsFromRuntimePack(BuildArgs buildArgs, string shardName, string testedLocales, RunHost host, string id) =>
TestIcuShards(buildArgs, shardName, testedLocales, host, id);
}
Loading
Loading