diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9af10ce03..127dd1e35 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -21,11 +21,14 @@ jobs: - name: Build project run: dotnet build --configuration Release + # there are cases where this will fail and we want to know about it + # so we don't use continue-on-error, but we still want to publish the results - name: Test project - continue-on-error: true - run: dotnet test --filter "TestCategory != SkipOnTeamCity" --logger:"trx;LogFilePrefix=results" --results-directory ./test-results + id: test + run: dotnet test --filter "TestCategory != SkipOnTeamCity" --blame-hang-timeout 5m --logger:"trx;LogFilePrefix=results" --results-directory ./test-results - name: Publish test results + if: ${{ !cancelled() && steps.test.outcome != 'skipped' }} uses: EnricoMi/publish-unit-test-result-action/windows@v2 with: check_name: LibPalaso Tests diff --git a/SIL.Core/Reflection/ReflectionHelper.cs b/SIL.Core/Reflection/ReflectionHelper.cs index 898cc89c6..20787ee8d 100644 --- a/SIL.Core/Reflection/ReflectionHelper.cs +++ b/SIL.Core/Reflection/ReflectionHelper.cs @@ -464,7 +464,7 @@ public static string LongVersionNumberString } private static readonly bool RunningFromUnitTest = AppDomain.CurrentDomain.GetAssemblies() - .Any(assem => + .Any(assem => assem.FullName.StartsWith("nunit.framework", StringComparison.OrdinalIgnoreCase) || assem.FullName.StartsWith("Microsoft.VisualStudio.QualityTools.UnitTestFramework", StringComparison.OrdinalIgnoreCase) || assem.FullName.StartsWith("Microsoft.VisualStudio.TestPlatform.TestFramework", StringComparison.OrdinalIgnoreCase) diff --git a/SIL.Windows.Forms.Keyboarding/SIL.Windows.Forms.Keyboarding.csproj b/SIL.Windows.Forms.Keyboarding/SIL.Windows.Forms.Keyboarding.csproj index 243240267..f2d7fcd64 100644 --- a/SIL.Windows.Forms.Keyboarding/SIL.Windows.Forms.Keyboarding.csproj +++ b/SIL.Windows.Forms.Keyboarding/SIL.Windows.Forms.Keyboarding.csproj @@ -9,7 +9,7 @@ - + diff --git a/SIL.WritingSystems.Tests/AddSortKeysToXmlTests.cs b/SIL.WritingSystems.Tests/AddSortKeysToXmlTests.cs index dc4c1e848..12b30edeb 100644 --- a/SIL.WritingSystems.Tests/AddSortKeysToXmlTests.cs +++ b/SIL.WritingSystems.Tests/AddSortKeysToXmlTests.cs @@ -3,6 +3,7 @@ using System.Xml; using System.Xml.XPath; using NUnit.Framework; +using SIL.Base32; namespace SIL.WritingSystems.Tests { @@ -40,6 +41,16 @@ public void Setup() _sortKeyGenerator = CultureInfo.InvariantCulture.CompareInfo.GetSortKey; } + [Test] + public void VerifySortKeyGenerator() + { + var sortKey = _sortKeyGenerator("z"); + var sortKeyBase32 = Base32Convert.ToBase32HexString(sortKey.KeyData, Base32FormattingOptions.None); + //this may be over specified, but all the tests expect this to pass + Assert.AreEqual("1QKG20810400", sortKeyBase32); + Assert.AreEqual("z", sortKey.OriginalString); + } + [Test] public void AddSortKeys() { diff --git a/SIL.WritingSystems.Tests/IcuRulesCollationDefinitionTests.cs b/SIL.WritingSystems.Tests/IcuRulesCollationDefinitionTests.cs index d447688d4..c937c3eb2 100644 --- a/SIL.WritingSystems.Tests/IcuRulesCollationDefinitionTests.cs +++ b/SIL.WritingSystems.Tests/IcuRulesCollationDefinitionTests.cs @@ -80,5 +80,21 @@ public void Validate_ImportInvalidRules_NotValid() Assert.That(collation.Validate(out message), Is.False); Assert.That(message, Is.EqualTo("Unable to import the private collation rules from en-US.")); } + + [Test] + public void Collation_GetSortKeyWorks() + { + var ws = new WritingSystemDefinition("en-US"); + ws.Collations.Add(new IcuRulesCollationDefinition("private") + { IcuRules = "&B + $(TargetFrameworks);net8.0 Unit tests for SIL.WritingSystems + + + @@ -11,6 +15,8 @@ + + diff --git a/SIL.WritingSystems/CultureInfoExtensions.cs b/SIL.WritingSystems/CultureInfoExtensions.cs new file mode 100644 index 000000000..e49121074 --- /dev/null +++ b/SIL.WritingSystems/CultureInfoExtensions.cs @@ -0,0 +1,18 @@ +using System.Globalization; + +namespace SIL.WritingSystems +{ + public static class CultureInfoExtensions + { + public static bool IsUnknownCulture(this CultureInfo cultureInfo) + { + // Windows 10 changed the behavior of CultureInfo, in that unknown cultures no longer return a CultureInfo containing an "Unknown Language" indication. + // The proper way to detect fully unknown cultures (for Windows 11 and prior) is to: + // 1. Check for the custom culture flag + // 2. Check if the three-letter language name is set to default + // Source: https://stackoverflow.com/a/71388328/1964319 + return cultureInfo.CultureTypes.HasFlag(CultureTypes.UserCustomCulture) && + cultureInfo.ThreeLetterWindowsLanguageName == "ZZZ"; + } + } +} \ No newline at end of file diff --git a/SIL.WritingSystems/IcuRulesCollator.cs b/SIL.WritingSystems/IcuRulesCollator.cs index d3b4a7147..fd6fac7ea 100644 --- a/SIL.WritingSystems/IcuRulesCollator.cs +++ b/SIL.WritingSystems/IcuRulesCollator.cs @@ -62,37 +62,7 @@ public static bool ValidateSortRules(string rules, out string message) public SortKey GetSortKey(string source) { -#if NET461 return _collator.GetSortKey(source); -#elif NETSTANDARD2_0 - Icu.SortKey icuSortKey = _collator.GetSortKey(source); - SortKey sortKey = CultureInfo.InvariantCulture.CompareInfo.GetSortKey(string.Empty, CompareOptions.None); - string keyDataFieldName, origStringFieldName; - if (Platform.IsDotNetFramework) - { - keyDataFieldName = "m_KeyData"; - origStringFieldName = "m_String"; - } - else if (Platform.IsDotNetCore) - { - keyDataFieldName = "_keyData"; - origStringFieldName = "_string"; - } - else if (Platform.IsMono) - { - keyDataFieldName = "key"; - origStringFieldName = "source"; - } - else - { - throw new PlatformNotSupportedException(); - } - - SetInternalFieldForPublicProperty(sortKey, "SortKey.KeyData", keyDataFieldName, icuSortKey.KeyData); - SetInternalFieldForPublicProperty(sortKey, "SortKey.OriginalString", origStringFieldName, - icuSortKey.OriginalString); - return sortKey; -#endif } ///Compares two strings and returns a value indicating whether one is less than, @@ -114,24 +84,5 @@ public int Compare(object x, object y) { return Compare((string) x, (string) y); } - -#if NETSTANDARD2_0 - private static void SetInternalFieldForPublicProperty(object instance, string propertyName, string fieldName, - object value) - { - Type type = instance.GetType(); - - FieldInfo fieldInfo = type.GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic); - - Debug.Assert(fieldInfo != null, - "Unsupported runtime", - "Could not figure out an internal field for" + propertyName); - - if (fieldInfo == null) - throw new PlatformNotSupportedException(); - - fieldInfo.SetValue(instance, value); - } -#endif } } diff --git a/SIL.WritingSystems/IetfLanguageTag.cs b/SIL.WritingSystems/IetfLanguageTag.cs index b2f984fe1..ad3b3f45c 100644 --- a/SIL.WritingSystems/IetfLanguageTag.cs +++ b/SIL.WritingSystems/IetfLanguageTag.cs @@ -1350,7 +1350,7 @@ public static string GetLocalizedLanguageName(string languageTag, string uiLangu } if (IsNullOrWhiteSpace(langName)) langName = ci.EnglishName; - if (!ci.EnglishName.StartsWith("Unknown Language")) // Windows .Net behavior + if (!ci.IsUnknownCulture()) { MapIsoCodesToLanguageName.Add(key, langName); return langName; @@ -1435,7 +1435,7 @@ public static string GetNativeLanguageNameWithEnglishSubtitle(string code) englishNameSuffix = englishNameSuffix.Substring(0, idxCountry) + "))"; } langName = nativeName + englishNameSuffix; - if (!ci.EnglishName.StartsWith("Unknown Language")) // Windows .Net behavior + if (!ci.IsUnknownCulture()) { MapIsoCodeToSubtitledLanguageName.Add(code, langName); return langName; diff --git a/SIL.WritingSystems/SIL.WritingSystems.csproj b/SIL.WritingSystems/SIL.WritingSystems.csproj index ca4f1b81b..65d4698fd 100644 --- a/SIL.WritingSystems/SIL.WritingSystems.csproj +++ b/SIL.WritingSystems/SIL.WritingSystems.csproj @@ -12,7 +12,7 @@ - + diff --git a/appveyor.yml b/appveyor.yml index 327100da9..3587e5062 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -2,7 +2,7 @@ version: '{build}' branches: only: - master -image: Visual Studio 2019 +image: Visual Studio 2022 init: - cmd: | set GITVERSION_BUILD_NUMBER=%APPVEYOR_BUILD_NUMBER%