From 2d24698536334d7296863fe9bb61bb67ba9c01fe Mon Sep 17 00:00:00 2001 From: Meri Khamoyan <96171496+mkhamoyan@users.noreply.github.com> Date: Tue, 10 Sep 2024 14:54:19 +0200 Subject: [PATCH] [iOS] [HybridGlobalization] Throw PNSE when methods with matchLength are used (#107390) * Throw PlatformNotSupportedException for matchLength --- .../src/System/Globalization/CompareInfo.cs | 2 +- .../CompareInfo/CompareInfoTests.IndexOf.cs | 6 +- .../CompareInfoTests.LastIndexOf.cs | 4 +- .../Invariant/InvariantMode.cs | 68 +++++++++++-------- .../System/StringTests.cs | 10 +-- 5 files changed, 51 insertions(+), 39 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/CompareInfo.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/CompareInfo.cs index e1505d67b81a84..f60a8fa16558c3 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/CompareInfo.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/CompareInfo.cs @@ -1057,7 +1057,7 @@ private unsafe int IndexOf(ReadOnlySpan source, ReadOnlySpan value, { Debug.Assert(matchLengthPtr != null); *matchLengthPtr = 0; -#if TARGET_BROWSER +#if TARGET_BROWSER || TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS if (GlobalizationMode.Hybrid) { throw new PlatformNotSupportedException(SR.PlatformNotSupported_HybridGlobalizationWithMatchLength); diff --git a/src/libraries/System.Runtime/tests/System.Globalization.Tests/CompareInfo/CompareInfoTests.IndexOf.cs b/src/libraries/System.Runtime/tests/System.Globalization.Tests/CompareInfo/CompareInfoTests.IndexOf.cs index e5c46744ad9aec..88cddb5f51357f 100644 --- a/src/libraries/System.Runtime/tests/System.Globalization.Tests/CompareInfo/CompareInfoTests.IndexOf.cs +++ b/src/libraries/System.Runtime/tests/System.Globalization.Tests/CompareInfo/CompareInfoTests.IndexOf.cs @@ -138,7 +138,7 @@ public static IEnumerable IndexOf_TestData() } // Inputs where matched length does not equal value string length - if (!PlatformDetection.IsHybridGlobalizationOnBrowser) + if (!PlatformDetection.IsHybridGlobalizationOnBrowser && PlatformDetection.IsNotHybridGlobalizationOnApplePlatform) { yield return new object[] { s_germanCompare, "abc Strasse Strasse xyz", "stra\u00DFe", 0, 23, supportedIgnoreCaseIgnoreNonSpaceOptions, 4, 7 }; yield return new object[] { s_germanCompare, "abc stra\u00DFe stra\u00DFe xyz", "Strasse", 0, 21, supportedIgnoreCaseIgnoreNonSpaceOptions, 4, 6 }; @@ -246,7 +246,7 @@ static void RunSpanIndexOfTest(CompareInfo compareInfo, ReadOnlySpan sourc valueBoundedMemory.MakeReadonly(); Assert.Equal(expected, compareInfo.IndexOf(sourceBoundedMemory.Span, valueBoundedMemory.Span, options)); - if (!PlatformDetection.IsHybridGlobalizationOnBrowser) + if (!PlatformDetection.IsHybridGlobalizationOnBrowser && PlatformDetection.IsNotHybridGlobalizationOnApplePlatform) { Assert.Equal(expected, compareInfo.IndexOf(sourceBoundedMemory.Span, valueBoundedMemory.Span, options, out int actualMatchLength)); Assert.Equal(expectedMatchLength, actualMatchLength); @@ -334,7 +334,7 @@ public void IndexOf_Invalid() AssertExtensions.Throws("options", () => s_invariantCompare.IndexOf("Test's", 'b', 0, CompareOptions.StringSort)); AssertExtensions.Throws("options", () => s_invariantCompare.IndexOf("Test's", 'c', 0, 2, CompareOptions.StringSort)); AssertExtensions.Throws("options", () => s_invariantCompare.IndexOf("Test's".AsSpan(), "b".AsSpan(), CompareOptions.StringSort)); - if (PlatformDetection.IsHybridGlobalizationOnBrowser) + if (PlatformDetection.IsHybridGlobalizationOnBrowser || PlatformDetection.IsHybridGlobalizationOnApplePlatform) { Assert.Throws(() => s_invariantCompare.IndexOf("Test's".AsSpan(), "b".AsSpan(), CompareOptions.StringSort, out _)); Assert.Throws(() => s_invariantCompare.IndexOf("Test's".AsSpan(), "b".AsSpan(), CompareOptions.Ordinal | CompareOptions.IgnoreWidth, out _)); diff --git a/src/libraries/System.Runtime/tests/System.Globalization.Tests/CompareInfo/CompareInfoTests.LastIndexOf.cs b/src/libraries/System.Runtime/tests/System.Globalization.Tests/CompareInfo/CompareInfoTests.LastIndexOf.cs index d0ff70511b644c..69cf4c0c3ba4a4 100644 --- a/src/libraries/System.Runtime/tests/System.Globalization.Tests/CompareInfo/CompareInfoTests.LastIndexOf.cs +++ b/src/libraries/System.Runtime/tests/System.Globalization.Tests/CompareInfo/CompareInfoTests.LastIndexOf.cs @@ -253,7 +253,7 @@ static void RunSpanLastIndexOfTest(CompareInfo compareInfo, ReadOnlySpan s valueBoundedMemory.MakeReadonly(); Assert.Equal(expected, compareInfo.LastIndexOf(sourceBoundedMemory.Span, valueBoundedMemory.Span, options)); - if (!PlatformDetection.IsHybridGlobalizationOnBrowser) + if (!PlatformDetection.IsHybridGlobalizationOnBrowser && PlatformDetection.IsNotHybridGlobalizationOnApplePlatform) { Assert.Equal(expected, compareInfo.LastIndexOf(sourceBoundedMemory.Span, valueBoundedMemory.Span, options, out int actualMatchLength)); Assert.Equal(expectedMatchLength, actualMatchLength); @@ -348,7 +348,7 @@ public void LastIndexOf_Invalid() AssertExtensions.Throws("options", () => s_invariantCompare.LastIndexOf("Test's", 'a', 0, CompareOptions.StringSort)); AssertExtensions.Throws("options", () => s_invariantCompare.LastIndexOf("Test's", 'a', 0, 1, CompareOptions.StringSort)); AssertExtensions.Throws("options", () => s_invariantCompare.LastIndexOf("Test's", "a".AsSpan(), CompareOptions.StringSort)); - if (PlatformDetection.IsHybridGlobalizationOnBrowser) + if (PlatformDetection.IsHybridGlobalizationOnBrowser || PlatformDetection.IsHybridGlobalizationOnApplePlatform) { Assert.Throws(() => s_invariantCompare.LastIndexOf("Test's", "a".AsSpan(), CompareOptions.StringSort, out int matchLength)); Assert.Throws(() => s_invariantCompare.LastIndexOf("Test's", "a".AsSpan(), CompareOptions.Ordinal | CompareOptions.IgnoreWidth, out int matchLength)); diff --git a/src/libraries/System.Runtime/tests/System.Globalization.Tests/Invariant/InvariantMode.cs b/src/libraries/System.Runtime/tests/System.Globalization.Tests/Invariant/InvariantMode.cs index 91b098cd505b68..c5733728fe6642 100644 --- a/src/libraries/System.Runtime/tests/System.Globalization.Tests/Invariant/InvariantMode.cs +++ b/src/libraries/System.Runtime/tests/System.Globalization.Tests/Invariant/InvariantMode.cs @@ -898,14 +898,17 @@ static void TestCore(CompareInfo compareInfo, string source, string value, int s Assert.Equal(offsetResult, sourceBoundedSpan.IndexOf(valueBoundedSpan, GetStringComparison(options))); Assert.Equal(offsetResult, compareInfo.IndexOf(sourceBoundedSpan, valueBoundedSpan, options)); - Assert.Equal(offsetResult, compareInfo.IndexOf(sourceBoundedSpan, valueBoundedSpan, options, out int matchLength)); - if (offsetResult >= 0) - { - Assert.Equal(valueBoundedSpan.Length, matchLength); // Invariant mode should perform non-linguistic comparisons - } - else + if (PlatformDetection.IsNotHybridGlobalizationOnApplePlatform) { - Assert.Equal(0, matchLength); // not found + Assert.Equal(offsetResult, compareInfo.IndexOf(sourceBoundedSpan, valueBoundedSpan, options, out int matchLength)); + if (offsetResult >= 0) + { + Assert.Equal(valueBoundedSpan.Length, matchLength); // Invariant mode should perform non-linguistic comparisons + } + else + { + Assert.Equal(0, matchLength); // not found + } } } } @@ -958,14 +961,17 @@ static void TestCore(CompareInfo compareInfo, string source, string value, int s Assert.Equal(result, sourceBoundedSpan.LastIndexOf(valueBoundedSpan, GetStringComparison(options))); Assert.Equal(result, compareInfo.LastIndexOf(sourceBoundedSpan, valueBoundedSpan, options)); - Assert.Equal(result, compareInfo.LastIndexOf(sourceBoundedSpan, valueBoundedSpan, options, out int matchLength)); - if (result >= 0) - { - Assert.Equal(valueBoundedSpan.Length, matchLength); // Invariant mode should perform non-linguistic comparisons - } - else + if (PlatformDetection.IsNotHybridGlobalizationOnApplePlatform) { - Assert.Equal(0, matchLength); // not found + Assert.Equal(result, compareInfo.LastIndexOf(sourceBoundedSpan, valueBoundedSpan, options, out int matchLength)); + if (result >= 0) + { + Assert.Equal(valueBoundedSpan.Length, matchLength); // Invariant mode should perform non-linguistic comparisons + } + else + { + Assert.Equal(0, matchLength); // not found + } } } } @@ -993,14 +999,17 @@ public void TestIsPrefix(string source, string value, CompareOptions options, bo Assert.Equal(result, sourceBoundedSpan.StartsWith(valueBoundedSpan, GetStringComparison(options))); Assert.Equal(result, compareInfo.IsPrefix(sourceBoundedSpan, valueBoundedSpan, options)); - Assert.Equal(result, compareInfo.IsPrefix(sourceBoundedSpan, valueBoundedSpan, options, out int matchLength)); - if (result) - { - Assert.Equal(valueBoundedSpan.Length, matchLength); // Invariant mode should perform non-linguistic comparisons - } - else + if (PlatformDetection.IsNotHybridGlobalizationOnApplePlatform) { - Assert.Equal(0, matchLength); // not found + Assert.Equal(result, compareInfo.IsPrefix(sourceBoundedSpan, valueBoundedSpan, options, out int matchLength)); + if (result) + { + Assert.Equal(valueBoundedSpan.Length, matchLength); // Invariant mode should perform non-linguistic comparisons + } + else + { + Assert.Equal(0, matchLength); // not found + } } } } @@ -1028,14 +1037,17 @@ public void TestIsSuffix(string source, string value, CompareOptions options, bo Assert.Equal(result, sourceBoundedSpan.EndsWith(valueBoundedSpan, GetStringComparison(options))); Assert.Equal(result, compareInfo.IsSuffix(sourceBoundedSpan, valueBoundedSpan, options)); - Assert.Equal(result, compareInfo.IsSuffix(sourceBoundedSpan, valueBoundedSpan, options, out int matchLength)); - if (result) - { - Assert.Equal(valueBoundedSpan.Length, matchLength); // Invariant mode should perform non-linguistic comparisons - } - else + if (PlatformDetection.IsNotHybridGlobalizationOnApplePlatform) { - Assert.Equal(0, matchLength); // not found + Assert.Equal(result, compareInfo.IsSuffix(sourceBoundedSpan, valueBoundedSpan, options, out int matchLength)); + if (result) + { + Assert.Equal(valueBoundedSpan.Length, matchLength); // Invariant mode should perform non-linguistic comparisons + } + else + { + Assert.Equal(0, matchLength); // not found + } } } } diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/StringTests.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/StringTests.cs index e30a879728cb67..230ede85d79e06 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/StringTests.cs +++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/StringTests.cs @@ -804,14 +804,14 @@ public static IEnumerable Replace_StringComparison_TestData() yield return new object[] { "", "\0", "y", StringComparison.InvariantCulture, "" }; } - [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNotHybridGlobalizationOnBrowser))] + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNotHybridGlobalizationOnBrowser), nameof(PlatformDetection.IsNotHybridGlobalizationOnApplePlatform))] [MemberData(nameof(Replace_StringComparison_TestData))] public void Replace_StringComparison_ReturnsExpected(string original, string oldValue, string newValue, StringComparison comparisonType, string expected) { Assert.Equal(expected, original.Replace(oldValue, newValue, comparisonType)); } - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotInvariantGlobalization))] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotInvariantGlobalization), nameof(PlatformDetection.IsNotHybridGlobalizationOnApplePlatform))] [ActiveIssue("https://github.com/dotnet/runtime/issues/60568", TestPlatforms.Android | TestPlatforms.LinuxBionic)] [ActiveIssue("https://github.com/dotnet/runtime/issues/95503", typeof(PlatformDetection), nameof(PlatformDetection.IsHybridGlobalizationOnBrowser))] public void Replace_StringComparison_TurkishI() @@ -871,7 +871,7 @@ public static IEnumerable Replace_StringComparisonCulture_TestData() } } - [Theory] + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNotHybridGlobalizationOnApplePlatform))] [MemberData(nameof(Replace_StringComparisonCulture_TestData))] [ActiveIssue("https://github.com/dotnet/runtime/issues/95503", typeof(PlatformDetection), nameof(PlatformDetection.IsHybridGlobalizationOnBrowser))] public void Replace_StringComparisonCulture_ReturnsExpected(string original, string oldValue, string newValue, bool ignoreCase, CultureInfo culture, string expected) @@ -897,7 +897,7 @@ public void Replace_StringComparison_EmptyOldValue_ThrowsArgumentException() AssertExtensions.Throws("oldValue", () => "abc".Replace("", "def", true, CultureInfo.CurrentCulture)); } - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotInvariantGlobalization), nameof(PlatformDetection.IsNotHybridGlobalizationOnBrowser))] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotInvariantGlobalization), nameof(PlatformDetection.IsNotHybridGlobalizationOnBrowser), nameof(PlatformDetection.IsNotHybridGlobalizationOnApplePlatform))] public void Replace_StringComparison_WeightlessOldValue_WithOrdinalComparison_Succeeds() { Assert.Equal("abcdef", ("abc" + ZeroWidthJoiner).Replace(ZeroWidthJoiner, "def")); @@ -905,7 +905,7 @@ public void Replace_StringComparison_WeightlessOldValue_WithOrdinalComparison_Su Assert.Equal("abcdef", ("abc" + ZeroWidthJoiner).Replace(ZeroWidthJoiner, "def", StringComparison.OrdinalIgnoreCase)); } - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotInvariantGlobalization), nameof(PlatformDetection.IsNotHybridGlobalizationOnBrowser))] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotInvariantGlobalization), nameof(PlatformDetection.IsNotHybridGlobalizationOnBrowser), nameof(PlatformDetection.IsNotHybridGlobalizationOnApplePlatform))] public void Replace_StringComparison_WeightlessOldValue_WithLinguisticComparison_TerminatesReplacement() { Assert.Equal("abc" + ZeroWidthJoiner + "def", ("abc" + ZeroWidthJoiner + "def").Replace(ZeroWidthJoiner, "xyz", StringComparison.CurrentCulture));