From 8b917f2cb56ade7ddbf6aa9bafa0ced27b63842e Mon Sep 17 00:00:00 2001 From: Logan Bussell Date: Tue, 29 Oct 2024 12:49:13 -0700 Subject: [PATCH] Add globalization scenario test (#6012) --- .../FileHelper.cs | 4 +- .../Microsoft.DotNet.Docker.Tests.csproj | 1 + .../RuntimeImageTests.cs | 1 + .../TestAppArtifacts/GlobalizationTest.cs | 70 +++++++++++++++++ .../TestScenarios/GlobalizationScenario.cs | 76 +++++++++++++++++++ 5 files changed, 150 insertions(+), 2 deletions(-) create mode 100644 tests/Microsoft.DotNet.Docker.Tests/TestAppArtifacts/GlobalizationTest.cs create mode 100644 tests/Microsoft.DotNet.Docker.Tests/TestScenarios/GlobalizationScenario.cs diff --git a/tests/Microsoft.DotNet.Docker.Tests/FileHelper.cs b/tests/Microsoft.DotNet.Docker.Tests/FileHelper.cs index 7b02e0b725..8d0b2235b5 100644 --- a/tests/Microsoft.DotNet.Docker.Tests/FileHelper.cs +++ b/tests/Microsoft.DotNet.Docker.Tests/FileHelper.cs @@ -58,7 +58,7 @@ public static string DiffFiles(string file1Path, string file2Path, ITestOutputHe } } - public class TempFolderContext : IDisposable + public sealed class TempFolderContext : IDisposable { public TempFolderContext() { @@ -81,7 +81,7 @@ public void Dispose() } } - public class TempFileContext : IDisposable + public sealed class TempFileContext : IDisposable { public TempFileContext() { diff --git a/tests/Microsoft.DotNet.Docker.Tests/Microsoft.DotNet.Docker.Tests.csproj b/tests/Microsoft.DotNet.Docker.Tests/Microsoft.DotNet.Docker.Tests.csproj index 0aa5f9fbe2..e9bc86f316 100644 --- a/tests/Microsoft.DotNet.Docker.Tests/Microsoft.DotNet.Docker.Tests.csproj +++ b/tests/Microsoft.DotNet.Docker.Tests/Microsoft.DotNet.Docker.Tests.csproj @@ -26,6 +26,7 @@ + diff --git a/tests/Microsoft.DotNet.Docker.Tests/RuntimeImageTests.cs b/tests/Microsoft.DotNet.Docker.Tests/RuntimeImageTests.cs index f2c90088cc..f6fb89ad93 100644 --- a/tests/Microsoft.DotNet.Docker.Tests/RuntimeImageTests.cs +++ b/tests/Microsoft.DotNet.Docker.Tests/RuntimeImageTests.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using Microsoft.DotNet.Docker.Tests.TestScenarios; using Xunit; using Xunit.Abstractions; diff --git a/tests/Microsoft.DotNet.Docker.Tests/TestAppArtifacts/GlobalizationTest.cs b/tests/Microsoft.DotNet.Docker.Tests/TestAppArtifacts/GlobalizationTest.cs new file mode 100644 index 0000000000..a687a88c5b --- /dev/null +++ b/tests/Microsoft.DotNet.Docker.Tests/TestAppArtifacts/GlobalizationTest.cs @@ -0,0 +1,70 @@ +using System.Globalization; +using static System.Console; + +const string envVarName = "DOTNET_SYSTEM_GLOBALIZATION_INVARIANT"; +string envVarValue = Environment.GetEnvironmentVariable(envVarName) ?? "null"; +bool invariantModeEnvVarSetting = envVarValue == "true" || envVarValue == "1"; +bool invariantModeEnabled = IsInvariantModeEnabled(); + +string isEnabledString = $"Globalization invariant mode is {(invariantModeEnabled ? "enabled" : "disabled")}"; +WriteLine(isEnabledString); + +if (invariantModeEnabled != invariantModeEnvVarSetting) +{ + throw new Exception("Environment variable mis-match: " + isEnabledString + + $", but {envVarName} is set to `{envVarValue}`, which evaluates to {invariantModeEnvVarSetting}."); +} + +try +{ + WriteLine($"The following should {(invariantModeEnabled ? "" : "not ")}produce an exception:"); + TestGlobalizationFunctionality(); + TestTimeZoneFunctionality(); + if (invariantModeEnabled) + { + throw new Exception("Expected an exception when testing globalization functionality but one did not occur."); + } +} +catch (CultureNotFoundException) +{ + if (invariantModeEnabled) + { + WriteLine("Successfully caught a CultureNotFoundException, invariant mode is working as expected."); + } + else + { + throw; + } +} + +WriteLine("Globalization test succeeded"); + +void TestGlobalizationFunctionality() +{ + const int Value = 1337; + WriteLine($"Value: {Value}"); + WriteLine($" en-US: {Value.ToString("c", new CultureInfo("en-US"))}"); + WriteLine($" jp-JP: {Value.ToString("c", new CultureInfo("jp-JP"))}"); +} + +void TestTimeZoneFunctionality() +{ + DateTime localTime = DateTime.Now; + TimeZoneInfo pacificZone = TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time"); + DateTime pacificTime = TimeZoneInfo.ConvertTime(localTime, pacificZone); + WriteLine("Local Time: " + localTime); + WriteLine("Pacific Time: " + pacificTime); +} + +// https://stackoverflow.com/a/75299176 +bool IsInvariantModeEnabled() +{ + try + { + return CultureInfo.GetCultureInfo("en-US").NumberFormat.CurrencySymbol == "ยค"; + } + catch (CultureNotFoundException) + { + return true; + } +} diff --git a/tests/Microsoft.DotNet.Docker.Tests/TestScenarios/GlobalizationScenario.cs b/tests/Microsoft.DotNet.Docker.Tests/TestScenarios/GlobalizationScenario.cs new file mode 100644 index 0000000000..8d05de2867 --- /dev/null +++ b/tests/Microsoft.DotNet.Docker.Tests/TestScenarios/GlobalizationScenario.cs @@ -0,0 +1,76 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.IO; +using System.Threading.Tasks; +using FluentAssertions; + +namespace Microsoft.DotNet.Docker.Tests.TestScenarios; + +#nullable enable +public sealed class GlobalizationScenario : ITestScenario, IDisposable +{ + private const string Dockerfile = """ + ARG sdk_image + ARG runtime_image + + FROM ${sdk_image} AS sdk + RUN dotnet new console -n App -o /src --no-restore + WORKDIR /src + COPY Program.cs /src/Program.cs + RUN dotnet restore + RUN dotnet publish --no-restore -o /app + + FROM ${runtime_image} AS runtime + COPY --from=sdk /app /app/ + ENTRYPOINT ["/app/App"] + """; + + private readonly TempFolderContext _tempFolderContext = FileHelper.UseTempFolder(); + private readonly ProductImageData _imageData; + private readonly DotNetImageRepo _repo; + private readonly DockerHelper _dockerHelper; + + public GlobalizationScenario( + ProductImageData imageData, + DotNetImageRepo repo, + DockerHelper dockerHelper) + { + _imageData = imageData; + _repo = repo; + _dockerHelper = dockerHelper; + } + + public async Task ExecuteAsync() + { + // Setup project in temp dir + string dockerfilePath = Path.Combine(_tempFolderContext.Path, "Dockerfile"); + await File.WriteAllTextAsync(path: dockerfilePath, contents: Dockerfile); + + File.Copy( + sourceFileName: Path.Combine(DockerHelper.TestArtifactsDir, "GlobalizationTest.cs"), + destFileName: Path.Combine(_tempFolderContext.Path, "Program.cs")); + + string tag = nameof(GlobalizationScenario).ToLowerInvariant(); + _dockerHelper.Build( + tag: tag, + dockerfile: dockerfilePath, + contextDir: _tempFolderContext.Path, + pull: Config.PullImages, + buildArgs: + [ + $"sdk_image={_imageData.GetImage(DotNetImageRepo.SDK, _dockerHelper)}", + $"runtime_image={_imageData.GetImage(_repo, _dockerHelper)}", + ]); + + string containerName = ImageData.GenerateContainerName(nameof(GlobalizationScenario)); + string output = _dockerHelper.Run(tag, containerName); + + output.Should().NotBeNullOrWhiteSpace(); + output.Should().ContainEquivalentOf("Globalization test succeeded", Exactly.Once()); + } + + public void Dispose() => _tempFolderContext.Dispose(); +}