-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Replaced string.Compare with Buffer.EndsWith to fix #39140 #39853
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
Conversation
GrabYourPitchforks
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please also fix up other uses of string.Compare within this class (such as within the Equals method) and introduce unit tests for them. For example:
bool areEqual = new StringSegment("ae").Equals("\u00C6", StringComparer.InvariantCultureIgnoreCase);
Assert.True(areEqual);
src/libraries/Microsoft.Extensions.Primitives/src/StringSegment.cs
Outdated
Show resolved
Hide resolved
src/libraries/Microsoft.Extensions.Primitives/src/StringSegment.cs
Outdated
Show resolved
Hide resolved
|
I cannot run the tests for some reason, it kept complaining about wrong .NET SDK version (global.json would've wanted "preview 8" which doesn't even exist, current preview is 7). I changed the version to preview 7 and now it errors with |
|
I made the requested changes but I couldn't get the tests to run as I said. I tested this by just calling those functions from my code and they seem to work fine but I don't know if that's enough or is it mandatory to run unit tests. |
src/libraries/Microsoft.Extensions.Primitives/src/StringSegment.cs
Outdated
Show resolved
Hide resolved
|
Removed that if clause, anything else? |
|
Can't really think of anything aside from the unit test updates. To run the unit tests, make sure you have the proper tools (find your OS from https://github.com/dotnet/runtime/tree/master/docs/workflow/requirements) installed on your machine. Then, from the command line: build -s clr -c Release
build -s libs+libs.tests -rc Release -testThe first line will build System.Private.CoreLib and friends. The second line will build the rest of the libraries (including Microsoft.Extensions.*) and unit tests, then it'll run all of the unit tests. If you want to use Visual Studio to build & run tests, make sure you also have the latest nightly SDK installed from https://aka.ms/dotnet/net5/dev/Sdk/dotnet-sdk-win-x64.exe. You'll need to at minimum build the CLR + libraries (follow above instructions but leave off the Some good examples of tests would be ensuring that |
|
I added that unit test but it + 6 other tests fail. I don't know why, I'm tired of unit testing already. There shouldn't be any differences with string.Compare way of doing it and .Equals. Or are there? |
|
Can you also add a test for the scenario reported in #39140? Console.WriteLine(new StringSegment("/").EndsWith("/", StringComparison.Ordinal));
// prints False !!!To run the tests, after building the repo (see the libraries build doc), you can do the following: You can find the correct version of See https://github.com/dotnet/runtime/blob/master/docs/workflow/testing/libraries/testing.md |
|
I added that. |
|
The tests are failing with this change. Can you fix them? |
|
I don't even understand how I can fix it. Even GrabYourPitchforks said I should use this.AsSpan.EndsWith/StartsWith and I did that. Are there any differences between String.Compare and EndWith/StartsWith/Equals? public bool Equals(StringSegment other, StringComparison comparisonType)
{
return this.AsSpan().Equals(other.AsSpan(), comparisonType);
}
public bool EndsWith(string text, StringComparison comparisonType)
{
if (text == null)
{
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.text);
}
return this.AsSpan().EndsWith(text.AsSpan(), comparisonType);
}
public bool StartsWith(string text, StringComparison comparisonType)
{
if (text == null)
{
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.text);
}
return this.AsSpan().StartsWith(text.AsSpan(), comparisonType);
}All of those should do the same thing as the |
|
The |
|
I added those checks, still 3 test failures. <test name="Microsoft.Extensions.Primitives.StringSegmentTest.StringSegment_Equals_InvariantCultureIgnoreCase" type="Microsoft.Extensions.Primitives.StringSegmentTest" method="StringSegment_Equals_InvariantCultureIgnoreCase" time="0.0035022" result="Fail">
<failure exception-type="Xunit.Sdk.TrueException">
<message><![CDATA[Assert.True() Failure\r\nExpected: True\r\nActual: False]]></message>
<stack-trace><![CDATA[ at Microsoft.Extensions.Primitives.StringSegmentTest.StringSegment_Equals_InvariantCultureIgnoreCase() in D:\Workspace\dotnet\runtime\src\libraries\Microsoft.Extensions.Primitives\tests\StringSegmentTest.cs:line 612]]></stack-trace>
</failure>
</test>
<test name="Microsoft.Extensions.Primitives.StringSegmentTest.DefaultStringSegment_DoesNotEqualStringSegment(candidate: )" type="Microsoft.Extensions.Primitives.StringSegmentTest" method="DefaultStringSegment_DoesNotEqualStringSegment" time="0.0005672" result="Fail">
<failure exception-type="Xunit.Sdk.FalseException">
<message><![CDATA[Assert.False() Failure\r\nExpected: False\r\nActual: True]]></message>
<stack-trace><![CDATA[ at Microsoft.Extensions.Primitives.StringSegmentTest.DefaultStringSegment_DoesNotEqualStringSegment(StringSegment candidate) in D:\Workspace\dotnet\runtime\src\libraries\Microsoft.Extensions.Primitives\tests\StringSegmentTest.cs:line 541]]></stack-trace>
</failure>
</test>
<test name="Microsoft.Extensions.Primitives.StringSegmentTest.DefaultStringSegment_DoesNotEqualStringSegment(candidate: )" type="Microsoft.Extensions.Primitives.StringSegmentTest" method="DefaultStringSegment_DoesNotEqualStringSegment" time="0.0002969" result="Fail">
<failure exception-type="Xunit.Sdk.FalseException">
<message><![CDATA[Assert.False() Failure\r\nExpected: False\r\nActual: True]]></message>
<stack-trace><![CDATA[ at Microsoft.Extensions.Primitives.StringSegmentTest.DefaultStringSegment_DoesNotEqualStringSegment(StringSegment candidate) in D:\Workspace\dotnet\runtime\src\libraries\Microsoft.Extensions.Primitives\tests\StringSegmentTest.cs:line 541]]></stack-trace>
</failure>
</test> |
|
One test is failing because this line: Should instead read: if (!HasValue)Also, for the test you added at below: Please add the equivalent that calls |
|
Looks like some of the calls to Important: The calls to |
Replaced string.Compare in Microsoft.Extensions.Primitives.StringSegment string.Compare caused issues in StringSegment.EndsWith when the Buffer is only one character long. Fix #39140
|
I made the requested changes. |
|
@DKittenz Are you still not able to run tests locally? There's a decent number of CI failures that local runs would have caught. My comment on the |
|
I got the tests running now, I will be pushing the final commit when I get those tests to pass. |
|
For reference, the reason I said we need to remove the length checks is that two strings of different lengths might compare as equal under certain comparers. That was the basis of the last part of my comment at #39853 (comment). If the length checks remain (or |
public bool Equals(StringSegment other, StringComparison comparisonType)
{
return string.Compare(Buffer, Offset, other.Buffer, other.Offset, other.Length, comparisonType) == 0;
}This is what the |
|
Tagging subscribers to this area: @eerhardt, @maryamariyan |
|
@DKittenz Are you still interested in driving this? Let us know what you're thinking or whether you'd like us to take this over - no worries either way! |
|
I can still do it, I just never got the tests to pass. |
|
If you're having trouble getting the tests to run on your box, let us know what errors you're seeing and we'll see what we can do. If the tests are running but not passing, hopefully that's an indication we have good test coverage of this area? I'll take the optimistic view. 😀 |
|
It's the second one. I got the tests to run after a bit of tinkering around but they don't pass. There is always that one string somewhere that doesn't work with the changes I make. I'll see what I can do to it. |
|
Nevermind, I can't do this right now because of my schedule. I really need to focus on a project of mine with one of my friends. |
|
@DKittenz thanks for the progress. Closing this PR for now. We could assign you back later on the issue if you decide to later resume changes here. |
Replaced string.Compare with Buffer.EndsWith/StartsWith in both
StringSegment.EndsWith and StringSegment.StartsWith.
string.Compare caused issues in StringSegment.EndsWith when the Buffer
is only one character long.
Replaced string.Compare in StringSegment.StartsWith as well to make
both StartsWith and EndsWith function similarly.
EDIT: As @GrabYourPitchforks already said in that issue, both of those shouldn't be using string.Compare.
Fix #39140