Adding System.Drawing.Common.Drawing2D GraphicsPath tests. #20711 #21866
Conversation
@KostaVlev, It will cover your contributions to all .NET Foundation-managed open source projects. |
@KostaVlev, thanks for signing the contribution license agreement. We will now validate the agreement and then the pull request. |
…WindowsNanoServer. (dotnet#21866)
@@ -0,0 +1,3294 @@ | |||
// |
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.
@KostaVlev thanks for the contribution. Please prefix with these two lines:
// Licensed to the .NET Foundation under one or more agreements.
// See the LICENSE file in the project root for more information.
|
||
private static IEnumerable<object[]> GetBounds_TestData() | ||
{ | ||
yield |
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.
remove dead comments?
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.
Dan, I think the location of your comments were screwed up :P
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.
ack, I wonder how that happened? I don't think it was me.
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.
Something weird happened. There's quite a few random comments showing up on this line, including some of @hughbe .
|
||
private static IEnumerable<object[]> GetBounds_TestData() | ||
{ | ||
yield |
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 remove assert.ignores.
|
||
private static IEnumerable<object[]> GetBounds_TestData() | ||
{ | ||
yield |
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.
nit: 'says'
|
||
private static IEnumerable<object[]> GetBounds_TestData() | ||
{ | ||
yield |
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.
All these Skips -- I assume these are from Mono, but do they fail on the Windows copy as well? If so we probably should just delete the tests.
|
||
[ConditionalTheory(nameof(PlatformDetection) + "." + nameof(PlatformDetection.IsNotWindowsNanoServer))] | ||
[InlineData(FillMode.Alternate, FillMode.Winding)] | ||
public void Ctor_FillMode_Succses(FillMode alternate, FillMode winding) |
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.
Nit: "success"
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.
and below..
} | ||
|
||
[ConditionalTheory(nameof(PlatformDetection) + "." + nameof(PlatformDetection.IsNotWindowsNanoServer))] | ||
[InlineData(FillMode.Alternate, FillMode.Winding)] |
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.
I'm not sure what this InlineData achieves, the function just gets called once, right? If so it might as well be hard coded perhaps?
@dotnet-bot test Linux x64 Release Build please |
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.
Nice! Good stuff here. Main comments are
-
Remove dead comments
-
Remove skips
-
Dispose of any places you call
new GraphicsPath
(sorry!) -
Add param names to argument exceptions (don't forget to use AssertExtensions.Throws instead of Assert.Throws)
-
Use
Assert.Equal(IEnumerable<T>, IEnumerable<T>
instead of asserting each element one by one in an array
{ | ||
private class RunIfFontFamilyGenericMonospaceNotNull : TheoryAttribute | ||
{ | ||
public RunIfFontFamilyGenericMonospaceNotNull() |
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.
Is there really a platform where GenericMonospace returns null? We have tests that would fail if this were the case here
I say just remove this
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.
Agreed -- I don't think it's valid to just return "null" from GenericMonospace
, so let's not consider it a possibility here.
[ConditionalFact(nameof(PlatformDetection) + "." + nameof(PlatformDetection.IsNotWindowsNanoServer))] | ||
public void GraphicsPath_InvalidFillMode_ThrowsInvalidEnumArgumentException() | ||
{ | ||
Assert.Throws<InvalidEnumArgumentException>(() => new GraphicsPath().FillMode = ((FillMode)int.MaxValue)); |
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 add the param name and use `AssertExtensions here and elsewhere for all argument exceptions
AssertExtensions.Throws<InvalidEnumArgumentException>("value", () => ...);
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.
Also, could be now, or in the future: let's turn this type of method into a theory, and add more test cases for each side of the range
[ConditionalTheoy(nameof(PlatformDetection) + "." + nameof(PlatformDetection.IsNotWindowsNanoServer))]
[InlineData(FillMode.Alternate - 1)]
[InlineData(FillMode.Winding + 1)]
public void GraphicsPath_InvalidFillMode_ThrowsInvalidEnumArgumentException(FillMode fillMode)
{
AssertExtensions.Throws<InvalidEnumArgumentException>("value", () => ...);
}
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.
Also, you need to dispose the graphics path here:
using (var graphicsPath = new GraphicsPath())
{
}
[ConditionalFact(nameof(PlatformDetection) + "." + nameof(PlatformDetection.IsNotWindowsNanoServer))] | ||
public void PathPoints_EmptyPath_ThrowsArgumentException() | ||
{ | ||
Assert.Throws<ArgumentException>(() => Assert.Null(new GraphicsPath().PathPoints)); |
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.
This is weird. Can you remove the Assert.Null
?
[ConditionalFact(nameof(PlatformDetection) + "." + nameof(PlatformDetection.IsNotWindowsNanoServer))] | ||
public void PathTypes_EmptyPath_ThrowsArgumentException() | ||
{ | ||
Assert.Throws<ArgumentException>(() => Assert.Null(new GraphicsPath().PathTypes)); |
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.
Could you add a param name, remove the assert.Null, and wrap the path in a using block?
I'll stop commenting on these
[InlineData(49, 157, 75, 196, 102, 209)] | ||
public void AddLine_SamePoints_Success(int x1, int y1, int x2, int y2, int x3, int y3) | ||
{ | ||
|
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.
Nit: spaces at top of method
|
||
private static IEnumerable<object[]> GetBounds_TestData() | ||
{ | ||
yield |
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.
Woah! Long test! Maybe you could shorten it to
Assert.Equal(new int[] { 0, 1, 1, 129 ...}, gp.PathTypes);
|
||
private static IEnumerable<object[]> GetBounds_TestData() | ||
{ | ||
yield |
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.
Indeed!
|
||
private static IEnumerable<object[]> GetBounds_TestData() | ||
{ | ||
yield |
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.
Dead?
|
||
private static IEnumerable<object[]> GetBounds_TestData() | ||
{ | ||
yield |
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.
This name is kind of meaningless now - can you see what the original bug was and modernize the name
|
||
private static IEnumerable<object[]> GetBounds_TestData() | ||
{ | ||
yield |
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.
Super duper nit: double new line
using System.Drawing.Drawing2D; | ||
using Xunit; | ||
|
||
namespace Drawing2D |
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.
Namespace: System.Drawing.Drawing2D.Tests
|
||
namespace Drawing2D | ||
{ | ||
public class GraphicsPathTest |
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.
Super nit: pluralize class name and file name to GraphicsPathTests
using (GraphicsPath gp = new GraphicsPath()) | ||
{ | ||
gp.AddRectangle(new Rectangle(1, 1, 2, 2)); | ||
Assert.Equal(1f, gp.PathPoints[0].X); |
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.
Maybe Assert.Equal(new PointF(1, 1), gp.PathPoints[0])
would be clearer here and elsewhere
gpf.AddLines(floeatPoints); | ||
// all identical points are added | ||
Assert.Equal(4, gpf.PointCount); | ||
Assert.Equal(0, gpf.PathTypes[0]); |
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.
Could use Assert.Equal(IEnumerable<T>, IEnumerable<T>)
here and elsewhere (I'll stop commenting)
e.g
Assert.Equal(new int[] { 1, 1, 1 }, gpf.PathTypes);
Thanks for doing the review @hughbe . |
…phicsPath in using block. Adding param names to argument exceptions. Use Assert.Equal(IEnumerable<T>, IEnumerable<T> instead of asserting each element one by one in an array. dotnet#21866
I think I managed to fix the suggested changes form @danmosemsft and @hughbe :) |
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.
Overall this is very comprehensive and well-written. Thanks for the large contribution! I made a few comments, mainly about minor nits, and some style / organization cleanup I'd like to see.
} | ||
|
||
[ConditionalFact(nameof(PlatformDetection) + "." + nameof(PlatformDetection.IsNotWindowsNanoServer))] | ||
public void PathData_Says_CannotChange() |
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.
What does "Says" mean here? Can this just be PathData_CannotChange
?
} | ||
|
||
[ConditionalTheory(nameof(PlatformDetection) + "." + nameof(PlatformDetection.IsNotWindowsNanoServer))] | ||
[InlineData(1, 1, 2, 2)] |
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.
It feels odd that this is a Theory with just a single InlineData -- primarily because the AssertLine
calls below are assuming that only these data points are ever going to be passed in. Can AssertLine
at least be changed so that these values are passed in to it?
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.
I see that this is kind of a general pattern with much of the assertions in here. I think it's okay, but the use of InlineData is a little bit misleading, because the assertions in all these tests are very tightly coupled with these values, and they aren't parameterized. It would be a little bit cleaner if we do the following:
- Don't use Theory/InlineData, and add some comments to the assertion methods so that it's obvious which hard-coded values they are expecting.
or
- Parameterize the assertions and pass in these values.
This is more a comment about the readability / maintainability of the tests, not their correctness. The first option is probably better -- the second would be more complicated and we probably wouldn't get much out of it unless we added a bunch more test cases with different data.
} | ||
|
||
[ConditionalTheory(nameof(PlatformDetection) + "." + nameof(PlatformDetection.IsNotWindowsNanoServer))] | ||
[InlineData(1, 1, 2, 2)] |
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.
Same comment about the InlineData
and AssertLine
new Point(x1, y1), new Point(x1, y1) | ||
}; | ||
|
||
PointF[] floeatPoints = new PointF[] |
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.
typo: floatPoints
|
||
PointF[] floeatPoints = new PointF[] | ||
{ | ||
new PointF((float)x1, (float)y1), new PointF((float)x1, (float)y1), |
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.
I think these float
casts are unnecessary.
|
||
PointF[] floatPoints = new PointF[] | ||
{ | ||
new PointF((float)x1, (float)y1), new PointF((float)x2, (float)y2), |
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.
nit: float casts unnecessary.
Assert.Equal(20, gpi.PointCount); | ||
|
||
gpf.AddClosedCurve( | ||
new PointF[3] { new PointF((float)x1, (float)y1), new PointF((float)x2, (float)y2), new PointF((float)x3, (float)y3) }); |
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.
nit: float casts unnecessary. I'll stop commenting on this.
|
||
[ConditionalTheory(nameof(PlatformDetection) + "." + nameof(PlatformDetection.IsNotWindowsNanoServer))] | ||
[InlineData(1, 1, 2, 2)] | ||
public void AddEllipse_Rectangl_Success(int x, int y, int width, int height) |
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.
typo: Rectangl Rectangle
} | ||
|
||
[ConditionalFact(nameof(PlatformDetection) + "." + nameof(PlatformDetection.IsNotWindowsNanoServer))] | ||
public void AddPie_Rectangl_Success() |
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.
typo Rectangl Rectangle
using (GraphicsPath clone = Assert.IsType<GraphicsPath>(gp.Clone())) | ||
{ | ||
gp.Flatten(null); | ||
Assert.Equal(gp.PointCount, clone.PointCount); |
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.
Hm, for these Flatten tests: won't PointCount
be 0 for the entirety of this method anyways, for both GraphicsPaths? We aren't adding anything anywhere, just creating an empty path and cloning it. It seems like we might want to:
- Add something to the path
- Clone it
- Flatten it
- Then check the values of the original and clone
Does that make sense?
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.
Hmm -- I see there are tests down below that do roughly that. This is okay, then.
… single InlineData attributes. (dotnet#21866)
…s. Test CopyData_StartEndIndexesOutOfRange_ReturnsExpeced() fails with exception System.EntryPointNotFoundException : Unable to find an entry point named 'ZeroMemory' in DLL 'kernel32.dll' , issue is tracked in (#22026). (#20711)
@KostaVlev you have some merge conflicts:
Solve the merge conflicts, then
|
Hey @KostaVlev, your test changes look good to me now. I think your rebasing / merging went a bit wrong, though. The only remaining change in the PR is the test file change, but you'll also need to add it to the project file (which you previously had done). Can you add that change back in? I'd also like if you could rebase out some of the intermediate stuff, as well as the merge commits with |
@mellinoe I am not sure how to rebase out commits.. |
@KostaVlev That is fine -- I will just squash the commits from this into a single commit before merging. In the future, I would recommend just doing a |
…the pull request is merged.
…tnet#21866) * Adding System.Drawing.Common.Drawing2D GraphicsPath tests. #20711 * Adding ConditionalFact and ConditionalTheory. Tests will run if IsNotWindowsNanoServer. (dotnet#21866) * Removing dead comments. Removing skips, they don't work. Wrapping GraphicsPath in using block. Adding param names to argument exceptions. Use Assert.Equal(IEnumerable<T>, IEnumerable<T> instead of asserting each element one by one in an array. dotnet#21866 * Pluralizing the name GraphicsPathTest.cs dotnet#21866 * Changing the namespace to System.Drawing.Drawing2D.Tests * Some spelling corrections. Removing unnecessary float casts. Removing single InlineData attributes. (dotnet#21866) * Removing arguments from test methods that are not [Theory]. * Adding System.Drawing.Common.Drawing2D GraphicsPathIteratorTests tests. Test CopyData_StartEndIndexesOutOfRange_ReturnsExpeced() fails with exception System.EntryPointNotFoundException : Unable to find an entry point named 'ZeroMemory' in DLL 'kernel32.dll' , issue is tracked in (#22026). (#20711) * Updating System.Drawing.Common.Tests.csproj. * Removing not related change to dotnet#21866. I will commit this when the pull request is merged. * Reverting changes to System.Drawing.Common.Tests.csproj.
…efx#20711 (dotnet/corefx#21866) * Adding System.Drawing.Common.Drawing2D GraphicsPath tests. dotnet/corefx#20711 * Adding ConditionalFact and ConditionalTheory. Tests will run if IsNotWindowsNanoServer. (dotnet/corefx#21866) * Removing dead comments. Removing skips, they don't work. Wrapping GraphicsPath in using block. Adding param names to argument exceptions. Use Assert.Equal(IEnumerable<T>, IEnumerable<T> instead of asserting each element one by one in an array. dotnet/corefx#21866 * Pluralizing the name GraphicsPathTest.cs dotnet/corefx#21866 * Changing the namespace to System.Drawing.Drawing2D.Tests * Some spelling corrections. Removing unnecessary float casts. Removing single InlineData attributes. (dotnet/corefx#21866) * Removing arguments from test methods that are not [Theory]. * Adding System.Drawing.Common.Drawing2D GraphicsPathIteratorTests tests. Test CopyData_StartEndIndexesOutOfRange_ReturnsExpeced() fails with exception System.EntryPointNotFoundException : Unable to find an entry point named 'ZeroMemory' in DLL 'kernel32.dll' , issue is tracked in (dotnet/corefx#22026). (dotnet/corefx#20711) * Updating System.Drawing.Common.Tests.csproj. * Removing not related change to dotnet/corefx#21866. I will commit this when the pull request is merged. * Reverting changes to System.Drawing.Common.Tests.csproj. Commit migrated from dotnet/corefx@4d78ca0
Converting mono GraphicsPath tests and adding few new.