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

Allow restricting cultures creation with any arbitrary names in Globalization Invariant Mode #54247

Merged
merged 15 commits into from
Jul 1, 2021

Conversation

tarekgh
Copy link
Member

@tarekgh tarekgh commented Jun 15, 2021

This change addresses the second part of #43774

This change is forcing to throw exception when creating any culture other than Invariant culture when enabling the Globalization Invariant Mode. This will allow easier diagnosis of the failures when turning on the Globalization Invariant Mode.
When turning on the Invariant globalization mode the config switch System.Globalization.PredefinedCulturesOnly will be automatically turned on. If anyone for any reason want to get back to the old behavior which is allowing creating any cultures by providing Invariant culture data, can do that by explicitly turning off the System.Globalization.PredefinedCulturesOnly switch.

The breaking change doc is tracked by Restrict Cultures Creation in Globalization Invariant Mode issue.

@ghost
Copy link

ghost commented Jun 15, 2021

Tagging subscribers to this area: @tarekgh, @safern
See info in area-owners.md if you want to be subscribed.

Issue Details

This change addresses the second part of #43774

This change is allowing restricting creating cultures with any names different than Invariant culture name (which is empty string). The is opt-in behavior which can get by using the config switch System.Globalization.AllowInvariantCultureOnly or environment variable DOTNET_SYSTEM_GLOBALIZATION_INVARIANT_CULTURE_ONLY.

Anyone enables this mode will force any code creating a culture with names different than Invariant culture name "" to throw exception.

Author: tarekgh
Assignees: -
Labels:

area-System.Globalization

Milestone: -

@tarekgh tarekgh closed this Jun 16, 2021
@tarekgh tarekgh reopened this Jun 16, 2021
@tarekgh
Copy link
Member Author

tarekgh commented Jun 16, 2021

CC @safern

Copy link
Member

@safern safern left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. It seems like there are some Globalization trimming tests failing.

@dotnet dotnet deleted a comment from azure-pipelines bot Jun 17, 2021
@dotnet dotnet deleted a comment from azure-pipelines bot Jun 17, 2021
@dotnet dotnet deleted a comment from azure-pipelines bot Jun 17, 2021
@dotnet dotnet deleted a comment from azure-pipelines bot Jun 17, 2021
@dotnet dotnet deleted a comment from azure-pipelines bot Jun 17, 2021
@dotnet dotnet deleted a comment from azure-pipelines bot Jun 17, 2021
@tarekgh tarekgh added the breaking-change Issue or PR that represents a breaking API or functional change over a prerelease. label Jun 24, 2021
@ghost ghost added the needs-breaking-change-doc-created Breaking changes need an issue opened with https://github.com/dotnet/docs/issues/new?template=dotnet label Jun 24, 2021
@ghost
Copy link

ghost commented Jun 24, 2021

Tagging @dotnet/compat for awareness of the breaking change.

@danmoseley
Copy link
Member

(Signed off but someone else should check the linker/trimming stuff.)

@tarekgh
Copy link
Member Author

tarekgh commented Jun 30, 2021

I tried setting the environment variable there, but it looks this didn't affect the test.

  [wasm test] info: Running v8 --expose_wasm runtime.js -- --setenv=DOTNET_SYSTEM_GLOBALIZATION_PREDEFINED_CULTURES_ONLY=false --setenv=XHARNESS_DISABLE_COLORED_OUTPUT=true --run invariant_True.dll
  [wasm test]
  [wasm test]
  [wasm test] fail: console.error: Error: System.Globalization.CultureNotFoundException: Only the invariant culture is supported in globalization-invariant mode. See https://aka.ms/GlobalizationInvariantMode for more information. (Parameter 'name')
  [wasm test]
  [wasm test] fail: es-ES is an invalid culture identifier.
  [wasm test]

The last idea I have is to force the value of PredefinedCulturesOnly in the test to false through the reflection. @marek-safar @lewing @radical if you have better idea please let me know.

@radical
Copy link
Member

radical commented Jul 1, 2021

Can you share the change you made, and binlog for the test?

@tarekgh
Copy link
Member Author

tarekgh commented Jul 1, 2021

@radical the test change is just creating the envVars and passing it to RunAndTestWasmApp

            Dictionary<string, string> envVars = new();
            envVars.Add("DOTNET_SYSTEM_GLOBALIZATION_PREDEFINED_CULTURES_ONLY", "false");

            RunAndTestWasmApp(buildArgs, expectedExitCode: 42,
                                test: output => Assert.Contains(expectedOutputString, output), host: host, id: id, envVars: envVars);

Looking at the logs, I am seeing the test src/tests/BuildWasmApps/Wasm.Build.Tests/InvariantGlobalizationTests.cs will get trimmed during building. Looks the behavior would be defined during building and not during the runtime. if this true, it would be difficult to control that behavior for the newly introduced property PredefinedCulturesOnly as we don't have msbuild property to control that yet.

I guess the best to do now, is to modify the test to catch the exception and use Invariant culture at that time. I'll try that and see how it goes.

/cc @eerhardt

@tarekgh tarekgh force-pushed the GlobalizationInvariantRestrictedMode branch from 62f2c4f to 8c503e1 Compare July 1, 2021 01:20
@tarekgh
Copy link
Member Author

tarekgh commented Jul 1, 2021

I fixed the browser test, hopefully this will be last failure :-)

internal static bool Invariant { get; } = GetInvariantSwitchValue();
internal static readonly bool PredefinedCulturesOnly = AppContextConfigHelper.GetBooleanConfig("System.Globalization.PredefinedCulturesOnly", "DOTNET_SYSTEM_GLOBALIZATION_PREDEFINED_CULTURES_ONLY", Invariant);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are Invariant and PredefinedCulturesOnly not symmetric in their design? e.g. I was expecting to see:

internal static bool Invariant { get; } = GetInvariantSwitchValue();
internal static bool PredefinedCulturesOnly { get; } = GetPredefinedCulturesOnlySwitchValue();

Copy link
Member Author

@tarekgh tarekgh Jul 1, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because we decided to not introduce a new config switch with the new Invariant behavior. @jkotas suggested to use the PredefinedCulturesOnly switch which make a lot of sense. Now the default Invariant behavior is to throw for any non-Invariant culture. For that we have to have PredefinedCulturesOnly be true be default for Invariant. and be false by default for non-Invariant mode. The only difference for PredefinedCulturesOnly is the default value when it is not specified.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was asking a style question. GetPredefinedCulturesOnlySwitchValue() would return AppContextConfigHelper.GetBooleanConfig("System.Globalization.PredefinedCulturesOnly", "DOTNET_SYSTEM_GLOBALIZATION_PREDEFINED_CULTURES_ONLY", Invariant);, exactly what you're already initializing it to.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@stephentoub I am going to merge this change soon. please let me know if you have any concern.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just don't see why the shape of these is different. But it's not a blocker, it's just inconsistent.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry my reply crossed your reply. This is how it is done to help the linker for trimming purpose I guess. look at @marek-safar change bc27d49 which introduced that.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this done this way to allow the linker to trim GetInvariantSwitchValue when Invariant mode is one. Having GetPredefinedCulturesOnlySwitchValue will require more work from the linker to trim it too. @eerhardt or @marek-safar should have definitive answer here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this done this way to allow the linker to trim GetInvariantSwitchValue when Invariant mode is one.

I don't believe this is the case. I think it is inconsistent because this code has been refactored multiple times, and no one has made it consistent.

Having GetPredefinedCulturesOnlySwitchValue will require more work from the linker to trim it too.

I don't believe this is true either. Alternatively, the opposite approach could be taken to make the code look consistent:

internal static bool Invariant { get; } = AppContextConfigHelper.GetBooleanConfig("System.Globalization.Invariant", "DOTNET_SYSTEM_GLOBALIZATION_INVARIANT");
internal static bool PredefinedCulturesOnly { get; } = AppContextConfigHelper.GetBooleanConfig("System.Globalization.PredefinedCulturesOnly", "DOTNET_SYSTEM_GLOBALIZATION_PREDEFINED_CULTURES_ONLY", Invariant);

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll try to submit a PR to make this consistent.

@tarekgh
Copy link
Member Author

tarekgh commented Jul 1, 2021

I opened the issue #55026 to track the unrelated JIT test failure in Android x64.
The failures in System.Net tests are unrelated and already tracked by #54778

@tarekgh tarekgh merged commit 04dac7b into dotnet:main Jul 1, 2021
@tarekgh tarekgh deleted the GlobalizationInvariantRestrictedMode branch July 1, 2021 18:55
steveisok pushed a commit that referenced this pull request Jul 9, 2021
This is an attempt to address #47112 based on Egor's suggestion.

The changes:

- set IsInterpreting MSBuild property to 'true' in case of iOS;
- made System.Linq.Expressions.ExpressionCreator class internal static in order not to introduce new public type; otherwise it throws Type 'System.Linq.Expressions.ExpressionCreator<TDelegate>' does not exist in the reference but it does exist in the implementation.
-updated the iOS simulator functional test for AOT to verify the fix
- added PlatformDetection.IsLinqExpressionsBuiltWithIsInterpretingOnly which checks whether the System.Linq.Expressions is built with IsInterpreting property set to true. To do so, it uses reflection to verify the Expression.Accept method doesn't exist.
- disabled some failing library tests using ActiveIssue + PlatformDetection.
- updated the invariant functional test for the iOS simulator (b/c of Allow restricting cultures creation with any arbitrary names in Globalization Invariant Mode #54247)

Co-authored-by: Stephen Toub <stoub@microsoft.com>
radical added a commit to radical/runtime that referenced this pull request Jul 22, 2021
The following commit changed the behavior to throw `CultureNotFoundException`
when creating cultures in invariant mode.

```
commit 04dac7b
Author: Tarek Mahmoud Sayed <tarekms@microsoft.com>
Date:   Thu Jul 1 11:55:05 2021 -0700

    Allow restricting cultures creation with any arbitrary names in Globalization Invariant Mode (dotnet#54247)
```

This commit updates the corresponding test in `Wasm.Build.Tests` to
handle that explicitly.

Fixes dotnet#55838
radical added a commit that referenced this pull request Jul 22, 2021
The following commit changed the behavior to throw `CultureNotFoundException`
when creating cultures in invariant mode.

```
commit 04dac7b
Author: Tarek Mahmoud Sayed <tarekms@microsoft.com>
Date:   Thu Jul 1 11:55:05 2021 -0700

    Allow restricting cultures creation with any arbitrary names in Globalization Invariant Mode (#54247)
```

This commit updates the corresponding test in `Wasm.Build.Tests` to
handle that explicitly.

Fixes #55838
@ghost ghost locked as resolved and limited conversation to collaborators Jul 31, 2021
@ericstj ericstj added this to the 6.0.0 milestone Sep 30, 2021
@ericstj ericstj added breaking-change Issue or PR that represents a breaking API or functional change over a prerelease. needs-breaking-change-doc-created Breaking changes need an issue opened with https://github.com/dotnet/docs/issues/new?template=dotnet and removed breaking-change Issue or PR that represents a breaking API or functional change over a prerelease. needs-breaking-change-doc-created Breaking changes need an issue opened with https://github.com/dotnet/docs/issues/new?template=dotnet labels Sep 30, 2021
@tarekgh
Copy link
Member Author

tarekgh commented Sep 30, 2021

@ericstj the description of this issue already referenced the breaking change issue dotnet/docs#24849 and it is already merged to the docs https://docs.microsoft.com/en-us/dotnet/core/compatibility/globalization/6.0/culture-creation-invariant-mode

@tarekgh tarekgh removed the needs-breaking-change-doc-created Breaking changes need an issue opened with https://github.com/dotnet/docs/issues/new?template=dotnet label Sep 30, 2021
@ericstj
Copy link
Member

ericstj commented Sep 30, 2021

Thanks @tarekgh, removing that label will get it off my list 👍

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-System.Globalization breaking-change Issue or PR that represents a breaking API or functional change over a prerelease.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants