Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Add ReadOnlySpan string-like StartsWith and EndsWith API with globalization support#16223

Merged
ahsonkhan merged 18 commits into
dotnet:masterfrom
ahsonkhan:GlobalStringExtensions
Feb 14, 2018
Merged

Add ReadOnlySpan string-like StartsWith and EndsWith API with globalization support#16223
ahsonkhan merged 18 commits into
dotnet:masterfrom
ahsonkhan:GlobalStringExtensions

Conversation

@ahsonkhan
Copy link
Copy Markdown

@ahsonkhan ahsonkhan commented Feb 6, 2018

Part of https://github.com/dotnet/corefx/issues/21395#issuecomment-359906138

  • StartsWith
  • EndsWith

TODO:

Related PR: dotnet/corefx#26880

cc @jkotas, @stephentoub, @KrzysztofCwalina, @tarekgh, @JeremyKuhne

uint dwFindNLSStringFlags,
string lpStringSource,
ReadOnlySpan<char> lpStringSource,
int startSource,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The int index+length arguments are not needed now that you are passing in Span.

SR.ArgumentNull_String);
}

return IsPrefix(source.AsReadOnlySpan(), prefix.AsReadOnlySpan(), options);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

IsPrefix method is public virtual. What happens if somebody overrides it?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I don't follow. It was a public virtual method before so whoever overrides it has to implement it just as they would before. Are you asking if we should make the Span based API public as well?

internal virtual bool IsPrefix(ReadOnlySpan<char> source, ReadOnlySpan<char> prefix, CompareOptions options)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I believe Jan is highlighting that if someone is currently overriding it, and we switch code to use the new span-based IsPrefix method instead of the string-based IsPrefix method, we'll be bypassing the existing overrides.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

The span-based IsPrefix is an internal implementation detail of the string IsPrefix. How will the existing string IsPrefix overrides be affected by this change? Essentially, I just extracted the code from the string method into an internal span based method.

Copy link
Copy Markdown
Member

@stephentoub stephentoub Feb 6, 2018

Choose a reason for hiding this comment

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

How will the existing string IsPrefix overrides be affected by this change?

The new ones won't respect any existing overrides already in place.

A similar situation has arisen in streams in the past. Consider MemoryStream. Imagine you'd derived a MaxSizeMemoryStream : MemoryStream, where you overrode Write(byte[], int, int) to track how much data has been written and to throw an exception from Write if too much data is written. You've overridden all possible Write methods. Now in the next release we add a new virtual Write(Span) method, and code starts using it with your type. There's now a way to Write to this stream that doesn't respect the overrides and wishes of your type, such that more than the max can be written.

I don't know if it's something that needs to be addressed here; I'm just calling out a potential issue.

Copy link
Copy Markdown
Author

@ahsonkhan ahsonkhan Feb 6, 2018

Choose a reason for hiding this comment

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

Ah I see! Thanks for the explanation.

I understand that if we add new public span overloads and there are implicit conversions (like array to span), then existing overrides won't be called. However, public virtual bool IsPrefix(string source, string prefix, CompareOptions options) doesn't call any virtual methods. And unless someone explicitly casts the string to Span, the following method public virtual bool IsPrefix(string source, string prefix) will not call the internal IsPrefix(ROS...) method.

Given that no public surface area is changing, and the public virtual methods that have new span overloads are not calling other virtual methods, I am not seeing the potential issues.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

CompareInfo does not have a public instance constructor, so it is de-facto sealed. So this is not a problem.

return false;
}

return (CompareInfo.CompareOrdinalIgnoreCase(this, 0, value.Length, value, 0, value.Length) == 0);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Nit: You can change this to CompareOrdinalIgnoreCase(this, value) so that it calls the span version directly.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Making this change was affecting performance of the other cases, especially Ordinal. The implicit conversion seems to increase the switch/method size too much. Therefore, I have reverted this change.

Debug.Assert(!prefix.IsEmpty);
Debug.Assert((options & (CompareOptions.Ordinal | CompareOptions.OrdinalIgnoreCase)) == 0);

if (_isAsciiEqualityOrdinal && CanUseAsciiOrdinalForOptions(options) && source.IsFastSort() && prefix.IsFastSort())
Copy link
Copy Markdown
Author

@ahsonkhan ahsonkhan Feb 6, 2018

Choose a reason for hiding this comment

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

How should I deal with the fact that this method relies on string.IsFastSort() which doesn't exist on Span?

FCIMPL1(FC_BOOL_RET, COMString::IsFastSort, StringObject* thisRef) {

Copy link
Copy Markdown
Member

@jkotas jkotas Feb 6, 2018

Choose a reason for hiding this comment

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

Refactor the implementation so that it is not needed. It will be likely faster without it if done properly, even for the string case: https://github.com/dotnet/coreclr/issues/14320

/// <summary>
/// Determines whether the beginning of the span matches the specified value when compared using the specified comparison option.
/// </summary>
public static bool StartsWith(this ReadOnlySpan<char> span, ReadOnlySpan<char> value, StringComparison comparison)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

comparison -> comparisonType to match the naming used everywhere else.

/// <summary>
/// Determines whether the beginning of the span matches the specified value when compared using the specified comparison option.
/// </summary>
public static bool StartsWith(this ReadOnlySpan<char> span, ReadOnlySpan<char> value, StringComparison comparison)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Some of the other extensions methods in this file (e.g. AsBytes) uses source instead of span for the this parameter name. It'd be nice if the naming was consistent.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

The APIs where this is source have another span parameter as destination. The other ones don't. That is the reason for the inconsistency. If we feel strongly about the parameter renaming, I can do it in all methods.

cc @KrzysztofCwalina, @terrajobst

/// </summary>
public static bool StartsWith(this ReadOnlySpan<char> span, ReadOnlySpan<char> value, StringComparison comparison)
{
if ((uint)(comparison - StringComparison.CurrentCulture) > (StringComparison.OrdinalIgnoreCase - StringComparison.CurrentCulture))
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Any downside to moving this inside the length check below? e.g.

if (span.Length < value.Length)
{
    if ((uint)(comparison - StringComparison.CurrentCulture) > (StringComparison.OrdinalIgnoreCase - StringComparison.CurrentCulture))
    {
        throw new ArgumentException(SR.NotSupported_StringComparison, nameof(comparison));
    }

    return false;
}

Copy link
Copy Markdown
Author

@ahsonkhan ahsonkhan Feb 6, 2018

Choose a reason for hiding this comment

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

I wanted to maintain the code shape (borrowed from string). But I see your point. Since the switch statement already has a default which throws, we don't need to check this ahead of time for all cases.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

With the latest change, this feedback is no longer applicable.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

There's now an if (value.Length == 0) check. Move it inside that to avoid the unnecessary check in most cases?

throw new NotImplementedException();

case StringComparison.OrdinalIgnoreCase:
return CompareInfo.CompareOrdinalIgnoreCase(span, value) == 0;
Copy link
Copy Markdown
Member

@stephentoub stephentoub Feb 6, 2018

Choose a reason for hiding this comment

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

This isn't correct, is it? Shouldn't it be span.Slice(0, value.Length) rather than span?

Does this behave the same as with strings when value.Length == 0?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Steve is correct. this comparison is wrong. you should slice the span with the value length.

for value.Length === 0 this check should be performed early for all type of comparisons and we should return true at that time.


In reply to: 166247652 [](ancestors = 166247652)

case StringComparison.Ordinal:
// TODO: https://github.com/dotnet/corefx/issues/25182
// return span.StartsWith(value);
throw new NotImplementedException();
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Rather than throwing, can you put a basic implementation in place now and then follow-up subsequently with whatever changes/improvements you want? It should only be a few lines.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

right the implementation should be straight forward


In reply to: 166248055 [](ancestors = 166248055)

return IsSuffix(source.AsReadOnlySpan(), suffix.AsReadOnlySpan(), options);
}

internal virtual bool IsSuffix(ReadOnlySpan<char> source, ReadOnlySpan<char> suffix, CompareOptions options)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

As it's internal, if we don't override it anywhere, it doesn't need to be virtual.

case StringComparison.Ordinal:
// TODO: https://github.com/dotnet/corefx/issues/25182
// return span.EndsWith(value);
throw new NotImplementedException();
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Same comment/question as above.

if (span.Length < value.Length)
{
return false;
}
Copy link
Copy Markdown
Member

@stephentoub stephentoub Feb 6, 2018

Choose a reason for hiding this comment

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

Is this length check valid for all cultures? cc: @tarekgh #Closed

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

No, this check is wrong for culture aware cases


In reply to: 166252147 [](ancestors = 166252147)

throw new ArgumentException(SR.NotSupported_StringComparison, nameof(comparison));
}

if (span.Length < value.Length)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

if (span.Length < value.Length [](start = 12, length = 30)

same comment as StartsWith one

throw new NotImplementedException();

case StringComparison.OrdinalIgnoreCase:
return (CompareInfo.CompareOrdinalIgnoreCase(span.Slice(span.Length - value.Length), value) == 0);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

e(span.Length - value.Length), value) = [](start = 74, length = 39)

would you handle the case when value.Length == 0?

/// <summary>
/// Determines whether the beginning of the span matches the specified value when compared using the specified comparison option.
/// </summary>
public static bool StartsWith(this ReadOnlySpan<char> span, ReadOnlySpan<char> value, StringComparison comparison)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

l StartsWith(th [](start = 25, length = 15)

All exposed new APIs has to handle the InvariantMode cases and should perform the operations as ordinal/ignorecasing at that time

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Can you please provide an example of what you mean? We already have StringComparison.InvariantCultureIgnoreCase. What other mode needs to be handled?

Copy link
Copy Markdown
Member

@stephentoub stephentoub Feb 6, 2018

Choose a reason for hiding this comment

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

We added a global flag to .NET Core 2.0 that effectively says to ignore culture, so that even if code uses StringComparison.CurrentCulture, it'll end up using Ordinal, e.g.

if (_invariantMode)
{
if ((options & CompareOptions.IgnoreCase) != 0)
return CompareOrdinalIgnoreCase(string1, 0, string1.Length, string2, 0, string2.Length);
return String.CompareOrdinal(string1, string2);
}
return CompareString(string1.AsReadOnlySpan(), string2.AsReadOnlySpan(), options);

This is something someone sets when they don't care about cultures and either don't have the needed dependencies (e.g. ICU) or don't want to carry such dependencies due to size constraints.

dotnet/announcements#20

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

ignore this one. I am seeing we are calling CompareInfo which take care of the InvariantMode.

To let you know what I mean, you may look https://github.com/dotnet/coreclr/blob/master/src/mscorlib/shared/System/Globalization/CompareInfo.cs#L648

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

We added a global flag to .NET Core 2.0 that effectively says to ignore culture

Good to know. Ty.

ignore this one.

OK.

@ahsonkhan
Copy link
Copy Markdown
Author

ahsonkhan commented Feb 6, 2018

Does anyone know how I can get VS compiler support for the unix specific files in the System.Private.Corelib solution?

I expect something like this (which I get for most of the files in the solution):
image

But for *.Unix files, I get no feedback:
image

@tarekgh
Copy link
Copy Markdown
Member

tarekgh commented Feb 7, 2018

test Windows_NT x64_arm64_altjit Checked corefx_baseline
test Ubuntu x64 Checked corefx_baseline

@dotnet dotnet deleted a comment from dotnet-bot Feb 7, 2018
@dotnet dotnet deleted a comment from dotnet-bot Feb 7, 2018
@dotnet dotnet deleted a comment from dotnet-bot Feb 7, 2018
@ahsonkhan
Copy link
Copy Markdown
Author

I have to address this failure:

src\System\Globalization\CompareInfo.Unix.cs(282,68): error CS1503: Argument 2: cannot convert from 'char*' to 'string' [D:\j\workspace\x86_release_w---80850631\src\mscorlib\System.Private.CoreLib.csproj]
15:11:43 src\System\Globalization\CompareInfo.Unix.cs(282,92): error CS1503: Argument 4: cannot convert from 'char*' to 'string'

@dotnet dotnet deleted a comment from dotnet-bot Feb 8, 2018
@dotnet dotnet deleted a comment from dotnet-bot Feb 8, 2018
@dotnet dotnet deleted a comment from dotnet-bot Feb 8, 2018
@ahsonkhan
Copy link
Copy Markdown
Author

I ran the new corefx tests (from related PR) against these changes, locally, and the tests pass.

Is there any other feedback that needs to be addressed?

@ahsonkhan
Copy link
Copy Markdown
Author

@dotnet-bot test Alpine.3.6 x64 Debug Build
@dotnet-bot test OSX10.12 x64 Checked Innerloop Build and Test

@dotnet-bot test Windows_NT arm Cross Checked corefx_baseline Build and Test
@dotnet-bot test Windows_NT x64_arm64_altjit Checked corefx_baseline
@dotnet-bot test Ubuntu x64 Checked corefx_baseline
@dotnet-bot test Windows_NT x64 Checked corefx_baseline
@dotnet-bot test Windows_NT x86_arm_altjit Checked corefx_baseline
@dotnet-bot test Windows_NT x86 Checked corefx_baseline

@AndyAyersMS
Copy link
Copy Markdown
Member

When you get a chance, can you point me at the version of the code you wanted to write but found was slower? No need to hold up this PR for that though....

@ahsonkhan
Copy link
Copy Markdown
Author

Can you point me at the version of the code you wanted to write but found was slower?

https://github.com/dotnet/coreclr/blob/master/src/mscorlib/src/System/String.Comparison.cs#L1062
Essentially, I wanted to call the span APIs underneath the string ones:

public Boolean StartsWith(String value, StringComparison comparisonType)
{
    if ((Object)value == null)
    {
        throw new ArgumentNullException(nameof(value));
    }

    if (comparisonType < StringComparison.CurrentCulture || comparisonType > StringComparison.OrdinalIgnoreCase)
    {
        throw new ArgumentException(SR.NotSupported_StringComparison, nameof(comparisonType));
    }

    if ((Object)this == (Object)value)
    {
        return true;
    }

    if (value.Length == 0)
    {
        return true;
    }

    return this.AsReadOnlySpan().StartsWith(value.AsReadOnlySpan(), comparisonType);
}

@ahsonkhan
Copy link
Copy Markdown
Author

@dotnet-bot test OSX10.12 x64 Checked Innerloop Build and Test

@ahsonkhan
Copy link
Copy Markdown
Author

ahsonkhan commented Feb 9, 2018

@dotnet-bot test OSX10.12 x64 Checked Innerloop Build and Test

Most of the corefx_baseline test failures are unrelated (https://github.com/dotnet/coreclr/issues/16272):

19:37:45   Using D:\j\workspace\x86_arm_altji---ab413291\_\fx\bin\testhost\netcoreapp-Windows_NT-Release-x86\ as the test runtime folder.
19:37:45      System.Tests.MathTests.Floor_Double(value: 0, expectedResult: 0, allowedVariance: 0) [SKIP]
19:37:46         https://github.com/dotnet/coreclr/issues/10288
19:37:47   Executing in D:\j\workspace\x86_arm_altji---ab413291\_\fx\bin\tests\System.Runtime.InteropServices.Tests\netcoreapp-Windows_NT-Release-x86\ 
19:37:49   Running tests... Start time: 19:37:29.39
19:37:50   
19:37:50 
  Assert failure(PID 9540 [0x00002544], Thread: 7272 [0x1c68]): Assertion failed 'unreached' in 'System.Tests.MathTests:Cbrt(double,double,double)' (IL size 14)

Existing issue: https://github.com/dotnet/corefx/issues/23435

     System.Data.SqlClient.Tests.SqlConnectionBasicTests.IntegratedAuthConnectionTest [FAIL]
18:49:25   TDSServerEndPoint ConnectionTest Is Server Socket Bound: True Testing connectivity to the endpoint created for the server.
18:49:25   TDSServerEndPoint ConnectionTest Endpoint test successful.
18:49:25         System.Data.SqlClient.SqlException : Connection Timeout Expired.  The timeout period elapsed during the post-login phase.  The connection could have timed out while waiting for server to complete the login process and respond; Or it could have timed out while attempting to create multiple active connections.  The duration spent while attempting to connect to this server was - [Pre-Login] initialization=630; handshake=2405; [Login] initialization=47; authentication=66; [Post-Login] complete=1393; 
18:49:25         ---- System.ComponentModel.Win32Exception : The wait operation timed out
18:49:25         Stack Trace:
18:49:25   TDSServerEndPoint ConnectionTest Listener Thread Started 
18:49:25            D:\j\workspace\x64_arm64_alt---e876825d\_\fx\src\System.Data.SqlClient\src\System\Data\SqlClient\SqlInternalConnectionTds.cs(374,0): at System.Data.SqlClient.SqlInternalConnectionTds..ctor(DbConnectionPoolIdentity identity, SqlConnectionString connectionOptions, Object providerInfo, Boolean redirectedUserInstance, SqlConnectionString userConnectionOptions, SessionData reconnectSessionData, Boolean applyTransientFaultHandling)
18:49:25            D:\j\workspace\x64_arm64_alt---e876825d\_\fx\src\System.Data.SqlClient\src\System\Data\SqlClient\SqlConnectionFactory.cs(136,0): at System.Data.SqlClient.SqlConnectionFactory.CreateConnection(DbConnectionOptions options, DbConnectionPoolKey poolKey, Object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningConnection, DbConnectionOptions userOptions)
18:49:25            D:\j\workspace\x64_arm64_alt---e876825d\_\fx\src\System.Data.SqlClient\src\System\Data\ProviderBase\DbConnectionFactory.cs(113,0): at System.Data.ProviderBase.DbConnectionFactory.CreatePooledConnection(DbConnectionPool pool, DbConnection owningObject, DbConnectionOptions options, DbConnectionPoolKey poolKey, DbConnectionOptions userOptions)
18:49:25            D:\j\workspace\x64_arm64_alt---e876825d\_\fx\src\System.Data.SqlClient\src\System\Data\ProviderBase\DbConnectionPool.cs(758,0): at System.Data.ProviderBase.DbConnectionPool.CreateObject(DbConnection owningObject, DbConnectionOptions userOptions, DbConnectionInternal oldConnection)
18:49:25            D:\j\workspace\x64_arm64_alt---e876825d\_\fx\src\System.Data.SqlClient\src\System\Data\ProviderBase\DbConnectionPool.cs(1609,0): at System.Data.ProviderBase.DbConnectionPool.UserCreateRequest(DbConnection owningObject, DbConnectionOptions userOptions, DbConnectionInternal oldConnection)
18:49:25            D:\j\workspace\x64_arm64_alt---e876825d\_\fx\src\System.Data.SqlClient\src\System\Data\ProviderBase\DbConnectionPool.cs(1135,0): at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, UInt32 waitForMultipleObjectsTimeout, Boolean allowCreate, Boolean onlyOneCheckConnection, DbConnectionOptions userOptions, DbConnectionInternal& connection)
18:49:25            D:\j\workspace\x64_arm64_alt---e876825d\_\fx\src\System.Data.SqlClient\src\System\Data\ProviderBase\DbConnectionPool.cs(1046,0): at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal& connection)
18:49:25            D:\j\workspace\x64_arm64_alt---e876825d\_\fx\src\System.Data.SqlClient\src\System\Data\ProviderBase\DbConnectionFactory.cs(290,0): at System.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, DbConnectionInternal& connection)
18:49:25            D:\j\workspace\x64_arm64_alt---e876825d\_\fx\src\System.Data.SqlClient\src\System\Data\ProviderBase\DbConnectionInternal.cs(700,0): at System.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions)
18:49:25            D:\j\workspace\x64_arm64_alt---e876825d\_\fx\src\System.Data.SqlClient\src\System\Data\SqlClient\SqlConnection.cs(1040,0): at System.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry)
18:49:26            D:\j\workspace\x64_arm64_alt---e876825d\_\fx\src\System.Data.SqlClient\src\System\Data\SqlClient\SqlConnection.cs(584,0): at System.Data.SqlClient.SqlConnection.Open()
18:49:27   
18:49:28            D:\j\workspace\x64_arm64_alt---e876825d\_\fx\src\System.Data.SqlClient\tests\FunctionalTests\SqlConnectionBasicTests.cs(38,0): at System.Data.SqlClient.Tests.SqlConnectionBasicTests.IntegratedAuthConnectionTest()
18:49:28   === TEST EXECUTION SUMMARY ===

This one occurs due to the change here since we no longer check the out-of-range StringComparison ahead of time (to throw ArgumentException) and the default within the switch throws NotSupportedException instead. Should we consolidate and always throw ArgumentException since that is what the tests seem to expect:
https://github.com/dotnet/corefx/blob/master/src/System.Runtime/tests/System/Uri.MethodsTests.cs#L309

     System.Tests.UriMethodTests.Compare_Invalid [FAIL]
19:48:07         Assert.Throws() Failure
19:48:09         Expected: typeof(System.ArgumentException)
19:48:11         Actual:   typeof(System.NotSupportedException): The string comparison type passed in is currently not supported.
19:48:13         Stack Trace:
19:48:14               at System.String.Compare(String strA, String strB, StringComparison comparisonType)
19:48:16            D:\j\workspace\x86_arm_altji---ab413291\_\fx\src\System.Private.Uri\src\System\UriExt.cs(342,0): at System.Uri.Compare(Uri uri1, Uri uri2, UriComponents partsToCompare, UriFormat compareFormat, StringComparison comparisonType)
19:48:18            D:\j\workspace\x86_arm_altji---ab413291\_\fx\src\System.Runtime\tests\System\Uri.MethodsTests.cs(309,0): at System.Tests.UriMethodTests.<>c__DisplayClass15_0.<Compare_Invalid>b__0()
19:48:22      System.Tests.StringTests.Compare_Invalid [FAIL]
19:48:23         Assert.Throws() Failure
19:48:25         Expected: typeof(System.ArgumentException)
19:48:26         Actual:   typeof(System.NotSupportedException): The string comparison type passed in is currently not supported.
19:48:26         Stack Trace:
19:48:26               at System.String.Compare(String strA, String strB, StringComparison comparisonType)
19:48:26            D:\j\workspace\x86_arm_altji---ab413291\_\fx\src\System.Runtime\tests\System\StringTests.cs(744,0): at System.Tests.StringTests.<>c.<Compare_Invalid>b__25_0()
19:49:40   Finished:    System.Runtime.Serialization.Xml.ReflectionOnly.Tests
19:49:40   
19:49:40   === TEST EXECUTION SUMMARY ===

@ahsonkhan
Copy link
Copy Markdown
Author

@dotnet-bot test Ubuntu arm64 Cross Debug Innerloop Build

@ahsonkhan
Copy link
Copy Markdown
Author

@dotnet-bot test Windows_NT arm Cross Checked corefx_baseline Build and Test
@dotnet-bot test Windows_NT x64_arm64_altjit Checked corefx_baseline
@dotnet-bot test Ubuntu x64 Checked corefx_baseline
@dotnet-bot test Windows_NT x64 Checked corefx_baseline
@dotnet-bot test Windows_NT x86_arm_altjit Checked corefx_baseline
@dotnet-bot test Windows_NT x86 Checked corefx_baseline

@ahsonkhan
Copy link
Copy Markdown
Author

cc @saurabh500, @corivera - do you guys know why we are seeing test failures -
System.Data.SqlClient.SqlException : Connection Timeout Expired.

@ahsonkhan
Copy link
Copy Markdown
Author

@dotnet-bot test Ubuntu x64 Checked corefx_baseline
@dotnet-bot test Windows_NT x64_arm64_altjit Checked corefx_baseline
@dotnet-bot test Windows_NT x86 Checked corefx_baseline
@dotnet-bot test Windows_NT x86_arm_altjit Checked corefx_baseline

@ahsonkhan
Copy link
Copy Markdown
Author

Unrelated to this PR (https://github.com/dotnet/coreclr/issues/16331):

13:40:53   Assertion Failed
13:40:53   
13:40:53   
13:40:53      at System.Globalization.CompareInfo.IndexOfCore(String source, String target, Int32 startIndex, Int32 count, CompareOptions options, Int32* matchLengthPtr)
13:40:54      at System.Globalization.CompareInfo.IndexOf(String source, Char value, Int32 startIndex, Int32 count, CompareOptions options)
13:40:54      at System.String.Contains(Char value, StringComparison comparisonType)
13:40:54      at System.Tests.StringTests.Contains(String s, Char value, StringComparison comparisionType, Boolean expected) in /mnt/j/workspace/dotnet_coreclr/master/jitstress/x64_checked_ubuntu_corefx_baseline_prtest/_/fx/src/System.Runtime/tests/System/StringTests.netcoreapp.cs:line 144
13:40:54      at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor, Boolean wrapExceptions)
13:40:54      at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, BindingFlags invokeAttr, Object[] parameters, Object[] arguments)
13:40:54      at Xunit.Sdk.TestInvoker`1.<>c__DisplayClass46_1.<<InvokeTestMethodAsync>b__1>d.MoveNext()
13:40:54      at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)
...

@ahsonkhan
Copy link
Copy Markdown
Author

Since the CI failures are unrelated to the changes here (and are being addressed outside the PR), I am going to go ahead and merge this.

@ahsonkhan ahsonkhan merged commit 27af160 into dotnet:master Feb 14, 2018
@ahsonkhan ahsonkhan deleted the GlobalStringExtensions branch February 14, 2018 02:18
}

// See https://github.com/dotnet/coreclr/blob/master/src/utilcode/util_nodependencies.cpp#L970
private static readonly bool[] HighCharTable = new bool[0x80]
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

s_HighCharTable

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants