From 13083573d394e79ca55253119917b02e49005aeb Mon Sep 17 00:00:00 2001 From: Gertjan van Heertum Date: Tue, 18 Jun 2019 21:39:54 +0200 Subject: [PATCH 01/10] Initial update to NUnit Added the correct nuget packages and transformed the test tags to the new namespace. Implemented the NUnit cases in lexer issues tests. Some tests need some additonal work, but the basics are there. --- Tests/Svg.UnitTests/BoundsTests.cs | 17 ++++--- Tests/Svg.UnitTests/CssQueryTest.cs | 8 ++-- Tests/Svg.UnitTests/DpiTest.cs | 6 +-- Tests/Svg.UnitTests/ImageComparisonTest.cs | 44 ++++++++++--------- Tests/Svg.UnitTests/LargeEmbeddedImageTest.cs | 11 ++--- Tests/Svg.UnitTests/LexerIssueTests.cs | 39 +++++++--------- Tests/Svg.UnitTests/MarkerEndTest.cs | 8 ++-- Tests/Svg.UnitTests/MetafileRenderingTest.cs | 14 +++--- Tests/Svg.UnitTests/MultiThreadingTest.cs | 10 ++--- Tests/Svg.UnitTests/PercentageSizeTests.cs | 10 ++--- Tests/Svg.UnitTests/PrivateFontsTests.cs | 6 +-- .../Svg.UnitTests/SmallEmbeddingImageTest.cs | 6 +-- Tests/Svg.UnitTests/Svg.UnitTests.csproj | 13 ++---- .../Svg.UnitTests/SvgPointCollectionTests.cs | 6 +-- Tests/Svg.UnitTests/SvgTestHelper.cs | 2 +- .../SvgTextElementDeepCopyTest.cs | 11 ++--- Tests/Svg.UnitTests/SvgTextTests.cs | 12 ++--- 17 files changed, 99 insertions(+), 124 deletions(-) diff --git a/Tests/Svg.UnitTests/BoundsTests.cs b/Tests/Svg.UnitTests/BoundsTests.cs index 62bc20ddc..d32c5c745 100644 --- a/Tests/Svg.UnitTests/BoundsTests.cs +++ b/Tests/Svg.UnitTests/BoundsTests.cs @@ -1,5 +1,4 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; -using System.Drawing; +using NUnit.Framework; namespace Svg.UnitTests { @@ -8,13 +7,13 @@ namespace Svg.UnitTests /// (see issue 281). Only some basic elements are tested - this should be sufficient /// to verify the functionality for all path-based elements. /// - [TestClass] + [TestFixture] public class BoundsTests : SvgTestHelper { private const string BoundsTestSvg = "Issue281_Bounds.BoundsTest.svg"; private static SvgDocument testDocument; - [TestMethod] + [Test] public void TestLineBounds() { // x1="10" x2="30" y1="20" y2="40", default line thickness is 1 @@ -25,7 +24,7 @@ public void TestLineBounds() AssertEqualBounds("line-xform", 19.5f, -40.5f, 21, 21); } - [TestMethod] + [Test] public void TestRectangleBounds() { // x="10" y="30" width="10" height="20" @@ -36,7 +35,7 @@ public void TestRectangleBounds() AssertEqualBounds("rect-rot", -50.5f, 9.5f, 21f, 11f); } - [TestMethod] + [Test] public void TestGroupBounds() { // all lines from TestLineBounds() @@ -45,19 +44,19 @@ public void TestGroupBounds() AssertEqualBounds("rects", -50.5f, 9.5f, 81f, 51f); } - [TestMethod] + [Test] public void TestTranslatedGroupBounds() { AssertEqualBounds("lines-translated", -12.5f, -7, 31, 86); } - [TestMethod] + [Test] public void TestScaledGroupBounds() { AssertEqualBounds("lines-scaled", 19, -81, 62, 172); } - [TestMethod] + [Test] public void TestRotatedGroupBounds() { AssertEqualBounds("lines-rotated", -45.5f, 9.5f, 86, 31); diff --git a/Tests/Svg.UnitTests/CssQueryTest.cs b/Tests/Svg.UnitTests/CssQueryTest.cs index 81db06e88..b6d798875 100644 --- a/Tests/Svg.UnitTests/CssQueryTest.cs +++ b/Tests/Svg.UnitTests/CssQueryTest.cs @@ -1,7 +1,5 @@ using Svg.Css; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using System; -using Svg.ExCSS; +using NUnit.Framework; namespace Svg.UnitTests { @@ -9,7 +7,7 @@ namespace Svg.UnitTests ///This is a test class for CssQueryTest and is intended ///to contain all CssQueryTest Unit Tests /// - [TestClass()] + [NUnit.Framework.TestFixture] public class CssQueryTest { @@ -73,7 +71,7 @@ private void TestSelectorSpecificity(string selector, int specificity) ///A test for GetSpecificity /// ///Lifted from http://www.smashingmagazine.com/2007/07/27/css-specificity-things-you-should-know/, and http://css-tricks.com/specifics-on-css-specificity/ - [TestMethod()] + [Test] public void RunSpecificityTests() { TestSelectorSpecificity("*", 0x0); diff --git a/Tests/Svg.UnitTests/DpiTest.cs b/Tests/Svg.UnitTests/DpiTest.cs index a4478551a..3b94ff581 100644 --- a/Tests/Svg.UnitTests/DpiTest.cs +++ b/Tests/Svg.UnitTests/DpiTest.cs @@ -1,4 +1,4 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; +using NUnit.Framework; namespace Svg.UnitTests { @@ -6,13 +6,13 @@ namespace Svg.UnitTests /// Test that basic graphics operations work. Currently only supported /// on Windows, macOS, and Linux. /// - [TestClass] + [TestFixture] public class DpiTest { /// /// We should get a valid dpi (probably 72, 96 or similar). /// - [TestMethod] + [Test] public void TestDpiAboveZero() { Assert.IsTrue(SvgDocument.PointsPerInch > 0); diff --git a/Tests/Svg.UnitTests/ImageComparisonTest.cs b/Tests/Svg.UnitTests/ImageComparisonTest.cs index a7c60151b..edbd268b7 100644 --- a/Tests/Svg.UnitTests/ImageComparisonTest.cs +++ b/Tests/Svg.UnitTests/ImageComparisonTest.cs @@ -1,4 +1,4 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; +using NUnit.Framework; using System; using System.Collections.Generic; using System.Drawing; @@ -11,7 +11,7 @@ namespace Svg.UnitTests { /// /// - [TestClass] + [TestFixture] public class ImageComparisonTest { public TestContext TestContext { get; set; } @@ -49,8 +49,9 @@ private static IEnumerable GetData() /// Note that with the current test there are still a lot of false positives, /// so this is not a definitive test for image equality yet. /// - [TestMethod] - [DynamicData(nameof(GetData), DynamicDataSourceType.Method)] + [Test] + //TODO: The DynamicData should be fixed + //[DynamicData(nameof(GetData), DynamicDataSourceType.Method)] // [DataSource("Microsoft.VisualStudio.TestTools.DataSource.CSV",@"|DataDirectory|\..\..\PassingTests.csv","PassingTests#csv", DataAccessMethod.Sequential)] //public void CompareSvgImageWithReference() public void CompareSvgImageWithReference(string basePath, string baseName) @@ -65,20 +66,21 @@ public void CompareSvgImageWithReference(string basePath, string baseName) CompareSvgImageWithReferenceImpl(baseName, svgPath, pngPath, testSaveLoad); } #else - [TestMethod] - [DataSource("Microsoft.VisualStudio.TestTools.DataSource.CSV", - @"|DataDirectory|\..\..\..\PassingTests.csv", - "PassingTests#csv", DataAccessMethod.Sequential)] + [Test] + //TODO: Same goes for the datasource here + //[DataSource("Microsoft.VisualStudio.TestTools.DataSource.CSV", + // @"|DataDirectory|\..\..\..\PassingTests.csv", + // "PassingTests#csv", DataAccessMethod.Sequential)] public void CompareSvgImageWithReference() { - var basePath = TestContext.TestRunDirectory; + var basePath = ""; //TODO: This was interpreted from the context -> TestContext.TestRunDirectory; while (!basePath.ToLower().EndsWith("svg")) { basePath = Path.GetDirectoryName(basePath); } basePath = Path.Combine(Path.Combine(basePath, "Tests"), "W3CTestSuite"); var svgBasePath = Path.Combine(basePath, "svg"); - var baseName = TestContext.DataRow[0] as string; + var baseName = ""; //TODO: Was read from import, replace -> TestContext.DataRow[0] as string; bool testSaveLoad = !baseName.StartsWith("#"); if (!testSaveLoad) { @@ -133,13 +135,13 @@ private void CompareSvgImageWithReferenceImpl(string baseName, /// of all considered W3C tests. /// Can be used to enhance the difference calculation. /// - // [TestClass] + // [TestFixture] public void RecordDiffForAllSvgImagesWithReference() { #if NETCORE var basePath = Path.Combine(GetSuiteTestsFolder, "W3CTestSuite"); #else - var basePath = Path.GetDirectoryName(Path.GetDirectoryName(Path.GetDirectoryName(TestContext.TestRunDirectory))); + var basePath = ""; //TODO: Tthe get dir name was parsed from the testparams -> Path.GetDirectoryName(Path.GetDirectoryName(Path.GetDirectoryName(TestContext.TestRunDirectory))); basePath = Path.Combine(Path.Combine(basePath, "Tests"), "W3CTestSuite"); #endif // var svgBasePath = Path.Combine(basePath, "svg"); @@ -284,15 +286,15 @@ public static Image GetGrayScaleVersion(this Image original) using (Graphics g = Graphics.FromImage(newBitmap)) { //create some image attributes - using (ImageAttributes attributes = new ImageAttributes()) - { - //set the color matrix attribute - attributes.SetColorMatrix(ColorMatrix); - - //draw the original image on the new image - //using the grayscale color matrix - g.DrawImage(original, new Rectangle(0, 0, original.Width, original.Height), - 0, 0, original.Width, original.Height, GraphicsUnit.Pixel, attributes); + using (ImageAttributes attributes = new ImageAttributes()) + { + //set the color matrix attribute + attributes.SetColorMatrix(ColorMatrix); + + //draw the original image on the new image + //using the grayscale color matrix + g.DrawImage(original, new Rectangle(0, 0, original.Width, original.Height), + 0, 0, original.Width, original.Height, GraphicsUnit.Pixel, attributes); } } return newBitmap; diff --git a/Tests/Svg.UnitTests/LargeEmbeddedImageTest.cs b/Tests/Svg.UnitTests/LargeEmbeddedImageTest.cs index 47fede7af..78a0281e6 100644 --- a/Tests/Svg.UnitTests/LargeEmbeddedImageTest.cs +++ b/Tests/Svg.UnitTests/LargeEmbeddedImageTest.cs @@ -1,9 +1,4 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; -using Svg.DataTypes; -using System; -using System.Diagnostics; -using System.Drawing; -using System.IO; +using NUnit.Framework; namespace Svg.UnitTests { @@ -16,13 +11,13 @@ namespace Svg.UnitTests /// Test use the following embedded resources: /// - Issue225_LargeUri\Speedometer.svg /// - [TestClass] + [TestFixture] public class LargeEmbeddedImageTest : SvgTestHelper { protected override string TestResource { get { return GetFullResourceString("Issue225_LargeUri.Speedometer.svg"); } } protected override int ExpectedSize { get { return 160000; } } - [TestMethod] + [Test] public void TestImageIsRendered() { LoadSvg(GetXMLDocFromResource()); diff --git a/Tests/Svg.UnitTests/LexerIssueTests.cs b/Tests/Svg.UnitTests/LexerIssueTests.cs index 8bb76f260..82f4ad00e 100644 --- a/Tests/Svg.UnitTests/LexerIssueTests.cs +++ b/Tests/Svg.UnitTests/LexerIssueTests.cs @@ -1,8 +1,4 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; +using NUnit.Framework; namespace Svg.UnitTests { @@ -13,7 +9,7 @@ namespace Svg.UnitTests /// /// This test class will test against these issues to prevent the bug from reoccuring /// - [TestClass] + [TestFixture] public class LexerIssueTests : SvgTestHelper { private const string ResourceStringEmptyDTagFile = "Issue399_LexerIssue.EmptyDTag.svg"; @@ -25,7 +21,7 @@ public class LexerIssueTests : SvgTestHelper /// /// We encountered issues in the example file that were caused by an empty d tag in some of the elements /// - [TestMethod] + [Test] public void Lexer_FileWithEmptyDAttribute_Success() { var xml = GetXMLDocFromResource(GetFullResourceString(ResourceStringEmptyDTagFile)); @@ -35,32 +31,31 @@ public void Lexer_FileWithEmptyDAttribute_Success() /// /// Stylesheet lexer fails if there is an important after a hex value, this tests the 3 and 6 lenght variants in the file /// - [TestMethod] - public void Lexer_ImportantAfterHex_Success() + [Test] + [TestCase("border-top: 1px solid #333 !important;")] //Important should be valid on 3 digit hex + [TestCase("border-top: 1px solid #009c46 !important;")] //Important should be valid on 6 digit hex + [TestCase("border-bottom: 1px solid #009c46 ;")] //Whitespace should not break the parser + public void Lexer_ImportantAfterHex_Success(string testString) { - //Important should be valid on 3 digit hex - GenerateLexerTestFile("border-top: 1px solid #333 !important;"); - //Important should be valid on 6 digit hex - GenerateLexerTestFile("border-top: 1px solid #009c46 !important;"); - //Whitespace should not break the parser - GenerateLexerTestFile("border-bottom: 1px solid #009c46 ;"); + GenerateLexerTestFile(testString); } /// ///Reference test if there is an important after a non-hex value (should never fail) and on hex without an important /// - [TestMethod] - public void Lexer_NoImportantAndImportantAfterNonHex_Success() + [Test] + + [TestCase("border-top: 1px solid #009c46;")] //Hex is working, if no !important suffixing it (#399) + [TestCase("border-top: 1px solid red !important;")] //Important is not failing on non-hex value + public void Lexer_NoImportantAndImportantAfterNonHex_Success(string testString) { - //Hex is working, if no !important suffixing it (#399) - GenerateLexerTestFile("border-top: 1px solid #009c46;"); - //Important is not failing on non-hex value - GenerateLexerTestFile("border-top: 1px solid red !important;"); + GenerateLexerTestFile(testString); } - [TestMethod] + [Test] public void Lexer_FileWithInvalidHex_ColorTagIsIgnored() { + //TODO: This test can be changed to TestCases or split to separate test // valid colors var doc = GenerateLexerTestFile("fill: #ff0000; stroke: #ffff00"); var path = doc.GetElementById("path1"); diff --git a/Tests/Svg.UnitTests/MarkerEndTest.cs b/Tests/Svg.UnitTests/MarkerEndTest.cs index bdd096efb..8185aefc2 100644 --- a/Tests/Svg.UnitTests/MarkerEndTest.cs +++ b/Tests/Svg.UnitTests/MarkerEndTest.cs @@ -1,4 +1,4 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; +using NUnit.Framework; using Svg.DataTypes; using System; using System.Diagnostics; @@ -16,7 +16,7 @@ namespace Svg.UnitTests /// Test use the following embedded resources: /// - Issue212_MakerEnd\OperatingPlan.svg /// - [TestClass] + [TestFixture] public class MarkerEndTest : SvgTestHelper { @@ -24,14 +24,14 @@ public class MarkerEndTest : SvgTestHelper protected override int ExpectedSize { get { return 4300; } } // original image has 4314 bytes - [TestMethod] + [Test] public void TestOperatingPlanRendering() { LoadSvg(GetXMLDocFromResource()); } - [TestMethod] + [Test] public void TestArrowCodeCreation() { // Sample code from Issue 212. Thanks to podostro. diff --git a/Tests/Svg.UnitTests/MetafileRenderingTest.cs b/Tests/Svg.UnitTests/MetafileRenderingTest.cs index 54d372aea..32a603c96 100644 --- a/Tests/Svg.UnitTests/MetafileRenderingTest.cs +++ b/Tests/Svg.UnitTests/MetafileRenderingTest.cs @@ -1,13 +1,8 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; +using NUnit.Framework; using System; -using System.Collections.Generic; -using System.Diagnostics; using System.Drawing; using System.Drawing.Imaging; using System.IO; -using System.Linq; -using System.Text; -using System.Xml; namespace Svg.UnitTests { @@ -20,15 +15,16 @@ namespace Svg.UnitTests /// Test use the following embedded resources: /// - Issue210_Metafile\3DSceneSnapshotBIG.svg /// - [TestClass] + [TestFixture] public class MetafileRenderingTest : SvgTestHelper { protected override string TestResource { get { return GetFullResourceString("Issue210_Metafile.3DSceneSnapshotBIG.svg"); } } protected override int ExpectedSize { get { return 12500; } } //12896 - [TestMethod] - [TestProperty(name: "speed", value: "slow")] + [Test] + //TODO: What does this one do? + //[TestProperty(name: "speed", value: "slow")] public void TestMetafileRendering() { LoadSvg(GetXMLDocFromResource()); diff --git a/Tests/Svg.UnitTests/MultiThreadingTest.cs b/Tests/Svg.UnitTests/MultiThreadingTest.cs index d2c97b834..9cd1850e4 100644 --- a/Tests/Svg.UnitTests/MultiThreadingTest.cs +++ b/Tests/Svg.UnitTests/MultiThreadingTest.cs @@ -1,15 +1,13 @@ #if NET35 #else -using Microsoft.VisualStudio.TestTools.UnitTesting; -using Svg.Exceptions; -using System; +using NUnit.Framework; using System.Diagnostics; using System.Threading.Tasks; namespace Svg.UnitTests { - [TestClass] + [TestFixture] public class MultiThreadingTest : SvgTestHelper { protected override string TestResource { get { return GetFullResourceString("Issue_Threading.TestFile.svg"); } } @@ -21,14 +19,14 @@ private void LoadFile() } - [TestMethod] + [Test] public void LoadSVGThreading_SingleThread_YieldsNoError() { LoadFile(); } - [TestMethod] + [Test] public void LoadSVGThreading_MultiThread_YieldsNoErrorWhileInBounds() { Parallel.For(0, 10, (x) => diff --git a/Tests/Svg.UnitTests/PercentageSizeTests.cs b/Tests/Svg.UnitTests/PercentageSizeTests.cs index 1fc75e8a6..d66dd31d5 100644 --- a/Tests/Svg.UnitTests/PercentageSizeTests.cs +++ b/Tests/Svg.UnitTests/PercentageSizeTests.cs @@ -1,11 +1,11 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; +using NUnit.Framework; namespace Svg.UnitTests { - [TestClass] + [TestFixture] public class PercentageSizeTests { - [TestMethod] + [Test] public void TestRectangle() { var svgRectangle = new SvgRectangle() @@ -18,7 +18,7 @@ public void TestRectangle() CheckPercentageSize(svgRectangle); } - [TestMethod] + [Test] public void TestCircle() { var svgCircle = new SvgCircle() @@ -30,7 +30,7 @@ public void TestCircle() CheckPercentageSize(svgCircle); } - [TestMethod] + [Test] public void TestEllipse() { var svgEllipse = new SvgEllipse() diff --git a/Tests/Svg.UnitTests/PrivateFontsTests.cs b/Tests/Svg.UnitTests/PrivateFontsTests.cs index 9d8ba886b..d415c0b38 100644 --- a/Tests/Svg.UnitTests/PrivateFontsTests.cs +++ b/Tests/Svg.UnitTests/PrivateFontsTests.cs @@ -1,4 +1,4 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; +using NUnit.Framework; using System.Drawing.Text; using System.Runtime.InteropServices; @@ -14,7 +14,7 @@ namespace Svg.UnitTests /// - Issue204_PrivateFont\Text.svg /// - Issue204_PrivateFont\BrushScriptMT2.ttf /// - [TestClass] + [TestFixture] public class PrivateFontsTests : SvgTestHelper { private const string PrivateFontSvg = "Issue204_PrivateFont.Text.svg"; @@ -23,7 +23,7 @@ public class PrivateFontsTests : SvgTestHelper protected override int ExpectedSize { get { return 3200; } } //3512 - [TestMethod] + [Test] public void TestPrivateFont() { AddFontFromResource(SvgElement.PrivateFonts, GetFullResourceString(PrivateFont)); diff --git a/Tests/Svg.UnitTests/SmallEmbeddingImageTest.cs b/Tests/Svg.UnitTests/SmallEmbeddingImageTest.cs index b0872bbe1..20c747485 100644 --- a/Tests/Svg.UnitTests/SmallEmbeddingImageTest.cs +++ b/Tests/Svg.UnitTests/SmallEmbeddingImageTest.cs @@ -1,4 +1,4 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; +using NUnit.Framework; namespace Svg.UnitTests { @@ -10,7 +10,7 @@ namespace Svg.UnitTests /// Test use the following embedded resources: /// - Issue225_LargeUri\Speedometer.svg /// - [TestClass] + [TestFixture] public class SmallEmbeddingImageTest : SvgTestHelper { protected override string TestResource @@ -29,7 +29,7 @@ protected override int ExpectedSize } } - [TestMethod] + [Test] public void TestImageIsRendered() { this.LoadSvg(this.GetXMLDocFromResource()); diff --git a/Tests/Svg.UnitTests/Svg.UnitTests.csproj b/Tests/Svg.UnitTests/Svg.UnitTests.csproj index 98761d7bd..86f793489 100644 --- a/Tests/Svg.UnitTests/Svg.UnitTests.csproj +++ b/Tests/Svg.UnitTests/Svg.UnitTests.csproj @@ -58,15 +58,10 @@ - - - - - - - - - + + + + diff --git a/Tests/Svg.UnitTests/SvgPointCollectionTests.cs b/Tests/Svg.UnitTests/SvgPointCollectionTests.cs index 08a848b7a..be0dfc2f9 100644 --- a/Tests/Svg.UnitTests/SvgPointCollectionTests.cs +++ b/Tests/Svg.UnitTests/SvgPointCollectionTests.cs @@ -1,13 +1,13 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; +using NUnit.Framework; namespace Svg.UnitTests { - [TestClass] + [TestFixture] public class SvgPointCollectionTests { - [TestMethod] + [Test] public void ToStringReturnsValidString() { var collection = new SvgPointCollection diff --git a/Tests/Svg.UnitTests/SvgTestHelper.cs b/Tests/Svg.UnitTests/SvgTestHelper.cs index be67530a3..15051aaa4 100644 --- a/Tests/Svg.UnitTests/SvgTestHelper.cs +++ b/Tests/Svg.UnitTests/SvgTestHelper.cs @@ -1,4 +1,4 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; +using NUnit.Framework; using System; using System.Diagnostics; using System.Drawing; diff --git a/Tests/Svg.UnitTests/SvgTextElementDeepCopyTest.cs b/Tests/Svg.UnitTests/SvgTextElementDeepCopyTest.cs index 04d9a5d09..6e423cbe1 100644 --- a/Tests/Svg.UnitTests/SvgTextElementDeepCopyTest.cs +++ b/Tests/Svg.UnitTests/SvgTextElementDeepCopyTest.cs @@ -1,4 +1,4 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; +using NUnit.Framework; using System.IO; using System.Linq; using System.Xml; @@ -10,12 +10,12 @@ namespace Svg.UnitTests /// text element has contains only text and now other elements like . /// /// - [TestClass] + [TestFixture] public class SvgTextElementDeepCopyTest : SvgTestHelper { private const string PureTextElementSvg = "Issue_TextElement.Text.svg"; - [TestMethod] + [Test] public void TestSvgTextElementDeepCopy() { var svgDocument = OpenSvg(GetResourceXmlDoc(GetFullResourceString(PureTextElementSvg))); @@ -31,9 +31,10 @@ public void TestSvgTextElementDeepCopy() /// The SVG document to check. private static void CheckDocument(SvgDocument svgDocument) { + //TODO: check if the assignablefrom indeed is the correct replacement Assert.AreEqual(2, svgDocument.Children.Count); - Assert.IsInstanceOfType(svgDocument.Children[0], typeof(SvgDefinitionList)); - Assert.IsInstanceOfType(svgDocument.Children[1], typeof(SvgText)); + Assert.IsAssignableFrom(typeof(SvgDefinitionList), svgDocument.Children[0]); + Assert.IsAssignableFrom(typeof(SvgText), svgDocument.Children[1]); var textElement = (SvgText)svgDocument.Children[1]; Assert.AreEqual("IP", textElement.Content); diff --git a/Tests/Svg.UnitTests/SvgTextTests.cs b/Tests/Svg.UnitTests/SvgTextTests.cs index 52c7d8a33..29309c4c4 100644 --- a/Tests/Svg.UnitTests/SvgTextTests.cs +++ b/Tests/Svg.UnitTests/SvgTextTests.cs @@ -1,18 +1,14 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; -using System; -using System.Collections.Generic; +using NUnit.Framework; using System.IO; -using System.Linq; -using System.Text; using System.Xml; namespace Svg.UnitTests { - [TestClass] + [TestFixture] public class SvgTextTests { - [TestMethod] + [Test] public void TextPropertyAffectsSvgOutput() { var document = new SvgDocument(); @@ -35,7 +31,7 @@ public void TextPropertyAffectsSvgOutput() /// We doing this indirectly by checking the Bound property, which uses the cache. /// The Bound coordinates must be updated after adding a X and a Y /// - [TestMethod] + [Test] public void ChangingCoordinatesInvalidatePathCache() { SvgText text = new SvgText(); From ff58eddfc08cb528dc53c7604a94701246be661f Mon Sep 17 00:00:00 2001 From: Gertjan van Heertum Date: Tue, 18 Jun 2019 21:45:19 +0200 Subject: [PATCH 02/10] Added remark regarding required change for SVG image test --- Tests/Svg.UnitTests/ImageComparisonTest.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Tests/Svg.UnitTests/ImageComparisonTest.cs b/Tests/Svg.UnitTests/ImageComparisonTest.cs index edbd268b7..0789ef51a 100644 --- a/Tests/Svg.UnitTests/ImageComparisonTest.cs +++ b/Tests/Svg.UnitTests/ImageComparisonTest.cs @@ -42,6 +42,8 @@ private static IEnumerable GetData() yield return new[] { (object)testSuite, (object)row, }; } + //TODO: The testcases should be fed with a custom element, refer to https://github.com/ObjectivityLtd/Ocaramba/wiki/NUnit-DataDriven-tests-from-Xml,-CSV-and-Excel-files for more information + /// /// Compares SVG images against reference PNG images from the W3C SVG 1.1 test suite. /// This tests 158 out of 179 passing tests - the rest will not pass From bbf98b14e4bf068184d3a6d561465da1f9a748f5 Mon Sep 17 00:00:00 2001 From: gvheertum Date: Wed, 19 Jun 2019 11:21:55 +0200 Subject: [PATCH 03/10] CSSQuery test now has TestCase for the Specifity test instead of a huge list of tests --- Tests/Svg.UnitTests/CssQueryTest.cs | 47 +++++++++++++++-------------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/Tests/Svg.UnitTests/CssQueryTest.cs b/Tests/Svg.UnitTests/CssQueryTest.cs index b6d798875..00216363a 100644 --- a/Tests/Svg.UnitTests/CssQueryTest.cs +++ b/Tests/Svg.UnitTests/CssQueryTest.cs @@ -72,29 +72,30 @@ private void TestSelectorSpecificity(string selector, int specificity) /// ///Lifted from http://www.smashingmagazine.com/2007/07/27/css-specificity-things-you-should-know/, and http://css-tricks.com/specifics-on-css-specificity/ [Test] - public void RunSpecificityTests() + [TestCase("*", 0x0)] + [TestCase("li", 0x10)] + [TestCase("li:first-line", 0x20)] + [TestCase("ul li", 0x20)] + [TestCase("ul ol+li", 0x30)] + [TestCase("h1 + *[rel=up]", 0x110)] + [TestCase("ul ol li.red", 0x130)] + [TestCase("li.red.level", 0x210)] + [TestCase("p", 0x010)] + [TestCase("div p", 0x020)] + [TestCase(".sith", 0x100)] + [TestCase("div p.sith", 0x120)] + [TestCase("#sith", 0x1000)] + [TestCase("body #darkside .sith p", 0x1120)] + [TestCase("body #content .data img:hover", 0x1220)] + [TestCase("a#a-02", 0x1010)] + [TestCase("a[id=\"a-02\"]", 0x0110)] + [TestCase("ul#nav li.active a", 0x1130)] + [TestCase("body.ie7 .col_3 h2 ~ h2", 0x0230)] + [TestCase("#footer *:not(nav) li", 0x1020)] + [TestCase("ul > li ul li ol li:first-letter", 0x0070)] + public void RunSpecificityTests(string selector, int specifity) { - TestSelectorSpecificity("*", 0x0); - TestSelectorSpecificity("li", 0x10); - TestSelectorSpecificity("li:first-line", 0x20); - TestSelectorSpecificity("ul li", 0x20); - TestSelectorSpecificity("ul ol+li", 0x30); - TestSelectorSpecificity("h1 + *[rel=up]", 0x110); - TestSelectorSpecificity("ul ol li.red", 0x130); - TestSelectorSpecificity("li.red.level", 0x210); - TestSelectorSpecificity("p", 0x010); - TestSelectorSpecificity("div p", 0x020); - TestSelectorSpecificity(".sith", 0x100); - TestSelectorSpecificity("div p.sith", 0x120); - TestSelectorSpecificity("#sith", 0x1000); - TestSelectorSpecificity("body #darkside .sith p", 0x1120); - TestSelectorSpecificity("body #content .data img:hover", 0x1220); - TestSelectorSpecificity("a#a-02", 0x1010); - TestSelectorSpecificity("a[id=\"a-02\"]", 0x0110); - TestSelectorSpecificity("ul#nav li.active a", 0x1130); - TestSelectorSpecificity("body.ie7 .col_3 h2 ~ h2", 0x0230); - TestSelectorSpecificity("#footer *:not(nav) li", 0x1020); - TestSelectorSpecificity("ul > li ul li ol li:first-letter", 0x0070); - } + TestSelectorSpecificity(selector, specifity); + } } } From d22940d989bb41e4c6049a3047d50ad70ff1dcfd Mon Sep 17 00:00:00 2001 From: gvheertum Date: Wed, 19 Jun 2019 11:22:17 +0200 Subject: [PATCH 04/10] Spitted some of the lexer tests instead of having a large assertion block --- Tests/Svg.UnitTests/LexerIssueTests.cs | 65 +++++++++++++++----------- 1 file changed, 38 insertions(+), 27 deletions(-) diff --git a/Tests/Svg.UnitTests/LexerIssueTests.cs b/Tests/Svg.UnitTests/LexerIssueTests.cs index 82f4ad00e..4699d9cb4 100644 --- a/Tests/Svg.UnitTests/LexerIssueTests.cs +++ b/Tests/Svg.UnitTests/LexerIssueTests.cs @@ -50,33 +50,44 @@ public void Lexer_ImportantAfterHex_Success(string testString) public void Lexer_NoImportantAndImportantAfterNonHex_Success(string testString) { GenerateLexerTestFile(testString); - } - - [Test] - public void Lexer_FileWithInvalidHex_ColorTagIsIgnored() - { - //TODO: This test can be changed to TestCases or split to separate test - // valid colors - var doc = GenerateLexerTestFile("fill: #ff0000; stroke: #ffff00"); - var path = doc.GetElementById("path1"); - Assert.AreEqual(System.Drawing.Color.Red, ((SvgColourServer)path.Fill).Colour); - Assert.AreEqual(System.Drawing.Color.Yellow, ((SvgColourServer)path.Stroke).Colour); - - // invalid/valid color combinations - default color is used for each invalid color - doc = GenerateLexerTestFile("fill: #ff00; stroke: #00ff00"); - path = doc.GetElementById("path1"); - // default fill color is Black - Assert.AreEqual(System.Drawing.Color.Black, ((SvgColourServer)path.Fill).Colour); - Assert.AreEqual(System.Drawing.Color.Lime, ((SvgColourServer)path.Stroke).Colour); - - doc = GenerateLexerTestFile("fill: #fff; stroke: 005577"); - path = doc.GetElementById("path1"); - Assert.AreEqual(System.Drawing.Color.White, ((SvgColourServer)path.Fill).Colour); - // default stroke color is null (transparent) - Assert.IsNull(path.Stroke); - - doc = GenerateLexerTestFile("fill:; stroke: #00557;"); - path = doc.GetElementById("path1"); + } + + [Test] + public void Lexer_FileWithValidHex_ColorTagIsIssued() + { + // valid colors + var doc = GenerateLexerTestFile("fill: #ff0000; stroke: #ffff00"); + var path = doc.GetElementById("path1"); + Assert.AreEqual(System.Drawing.Color.Red, ((SvgColourServer)path.Fill).Colour); + Assert.AreEqual(System.Drawing.Color.Yellow, ((SvgColourServer)path.Stroke).Colour); + } + + [Test] + public void Lexer_FileWithInvalidHex_ColorTagOnlyReverstToDefaultForTheInvalidTag() + { + // invalid/valid color combinations - default color is used for each invalid color + var doc = GenerateLexerTestFile("fill: #ff00; stroke: #00ff00"); + var path = doc.GetElementById("path1"); + // default fill color is Black + Assert.AreEqual(System.Drawing.Color.Black, ((SvgColourServer)path.Fill).Colour); + Assert.AreEqual(System.Drawing.Color.Lime, ((SvgColourServer)path.Stroke).Colour); + } + + [Test] + public void Lexer_FileWithInvalidHex_ColorTagResolvesToTransparent() + { + var doc = GenerateLexerTestFile("fill: #fff; stroke: 005577"); + var path = doc.GetElementById("path1"); + Assert.AreEqual(System.Drawing.Color.White, ((SvgColourServer)path.Fill).Colour); + // default stroke color is null (transparent) + Assert.IsNull(path.Stroke); + } + + [Test] + public void Lexer_FileWithInvalidHex_EmptyColorTagIsIgnored() + { + var doc = GenerateLexerTestFile("fill:; stroke: #00557;"); + var path = doc.GetElementById("path1"); Assert.AreEqual(System.Drawing.Color.Black, ((SvgColourServer)path.Fill).Colour); Assert.IsNull(path.Stroke); } From 7cd436ef6fad0604ffec11949c37ae91a84df8c5 Mon Sep 17 00:00:00 2001 From: gvheertum Date: Wed, 19 Jun 2019 11:22:39 +0200 Subject: [PATCH 05/10] Update to the image comparison tests to have a correct data source and to have them NUnit proof --- Tests/Svg.UnitTests/ImageComparisonTest.cs | 139 +++++++++++++-------- Tests/Svg.UnitTests/Svg.UnitTests.csproj | 4 +- 2 files changed, 90 insertions(+), 53 deletions(-) diff --git a/Tests/Svg.UnitTests/ImageComparisonTest.cs b/Tests/Svg.UnitTests/ImageComparisonTest.cs index 0789ef51a..c1a3d098a 100644 --- a/Tests/Svg.UnitTests/ImageComparisonTest.cs +++ b/Tests/Svg.UnitTests/ImageComparisonTest.cs @@ -6,7 +6,8 @@ using System.Drawing.Imaging; using System.IO; using System.Linq; - +using System.Reflection; + namespace Svg.UnitTests { /// @@ -16,35 +17,8 @@ public class ImageComparisonTest { public TestContext TestContext { get; set; } #if NETCORE - private static string _basePath = null; - private static string GetSuiteTestsFolder - { - get - { - if (_basePath != null) return _basePath; - var basePath = Environment.CurrentDirectory; - while (!basePath.ToLower().EndsWith("svg")) - { - basePath = Path.GetDirectoryName(basePath); - } - - _basePath = Path.Combine(basePath, "Tests"); - return _basePath; - } - } - - private static IEnumerable GetData() - { - var basePath = GetSuiteTestsFolder; - var testSuite = Path.Combine(basePath, "W3CTestSuite"); - var rows = File.ReadAllLines(Path.Combine(basePath, "Svg.UnitTests", "PassingTests.csv")).Skip(1); - foreach (var row in rows) - yield return new[] { (object)testSuite, (object)row, }; - } - - //TODO: The testcases should be fed with a custom element, refer to https://github.com/ObjectivityLtd/Ocaramba/wiki/NUnit-DataDriven-tests-from-Xml,-CSV-and-Excel-files for more information - - /// + + /// /// Compares SVG images against reference PNG images from the W3C SVG 1.1 test suite. /// This tests 158 out of 179 passing tests - the rest will not pass /// the test for several reasons. @@ -52,13 +26,12 @@ private static IEnumerable GetData() /// so this is not a definitive test for image equality yet. /// [Test] - //TODO: The DynamicData should be fixed - //[DynamicData(nameof(GetData), DynamicDataSourceType.Method)] - // [DataSource("Microsoft.VisualStudio.TestTools.DataSource.CSV",@"|DataDirectory|\..\..\PassingTests.csv","PassingTests#csv", DataAccessMethod.Sequential)] - //public void CompareSvgImageWithReference() - public void CompareSvgImageWithReference(string basePath, string baseName) + [TestCaseSource(typeof(ImageTestDataSource), nameof(ImageTestDataSource.PassingTests))] + public void CompareSvgImageWithReference(ImageTestDataSource.TestData testData) { - bool testSaveLoad = !baseName.StartsWith("#"); + string basePath = testData.BasePath; + string baseName = testData.BaseName; + bool testSaveLoad = !baseName.StartsWith("#"); if (!testSaveLoad) { baseName = baseName.Substring(1); @@ -66,23 +39,20 @@ public void CompareSvgImageWithReference(string basePath, string baseName) var svgPath = Path.Combine(basePath, "svg", baseName + ".svg"); var pngPath = Path.Combine(basePath, "png", baseName + ".png"); CompareSvgImageWithReferenceImpl(baseName, svgPath, pngPath, testSaveLoad); - } + } #else [Test] - //TODO: Same goes for the datasource here - //[DataSource("Microsoft.VisualStudio.TestTools.DataSource.CSV", - // @"|DataDirectory|\..\..\..\PassingTests.csv", - // "PassingTests#csv", DataAccessMethod.Sequential)] - public void CompareSvgImageWithReference() + [TestCaseSource(typeof(ImageTestDataSource), "PassingTests")] + public void CompareSvgImageWithReference(ImageTestDataSource.TestData testData) { - var basePath = ""; //TODO: This was interpreted from the context -> TestContext.TestRunDirectory; + var basePath = testData.BasePath; while (!basePath.ToLower().EndsWith("svg")) { basePath = Path.GetDirectoryName(basePath); } basePath = Path.Combine(Path.Combine(basePath, "Tests"), "W3CTestSuite"); var svgBasePath = Path.Combine(basePath, "svg"); - var baseName = ""; //TODO: Was read from import, replace -> TestContext.DataRow[0] as string; + var baseName = testData.BaseName; bool testSaveLoad = !baseName.StartsWith("#"); if (!testSaveLoad) { @@ -93,8 +63,8 @@ public void CompareSvgImageWithReference() CompareSvgImageWithReferenceImpl(baseName, svgPath, pngPath, testSaveLoad); } #endif - - private void CompareSvgImageWithReferenceImpl(string baseName, + + private void CompareSvgImageWithReferenceImpl(string baseName, string svgPath, string pngPath, bool testSaveLoad) { var pngImage = Image.FromFile(pngPath); @@ -139,15 +109,15 @@ private void CompareSvgImageWithReferenceImpl(string baseName, /// // [TestFixture] public void RecordDiffForAllSvgImagesWithReference() - { + { #if NETCORE - var basePath = Path.Combine(GetSuiteTestsFolder, "W3CTestSuite"); + var basePath = Path.Combine(ImageTestDataSource.SuiteTestsFolder, "W3CTestSuite"); #else - var basePath = ""; //TODO: Tthe get dir name was parsed from the testparams -> Path.GetDirectoryName(Path.GetDirectoryName(Path.GetDirectoryName(TestContext.TestRunDirectory))); + var basePath = Path.GetDirectoryName(Path.GetDirectoryName(Path.GetDirectoryName(TestContext.TestDirectory))); //TODO: Tthe get dir name was parsed from the testparams -> Path.GetDirectoryName(Path.GetDirectoryName(Path.GetDirectoryName(TestContext.TestRunDirectory))); basePath = Path.Combine(Path.Combine(basePath, "Tests"), "W3CTestSuite"); #endif - // var svgBasePath = Path.Combine(basePath, "svg"); - string[] lines = File.ReadAllLines(@"..\..\..\..\Tests\Svg.UnitTests\all.csv"); + // var svgBasePath = Path.Combine(basePath, "svg"); + string[] lines = File.ReadAllLines(@"..\..\..\..\Tests\Svg.UnitTests\all.csv"); foreach (var baseName in lines) { var svgPath = Path.Combine(Path.Combine(basePath, "svg"), baseName + ".svg"); @@ -323,4 +293,71 @@ public static Image GetGrayScaleVersion(this Image original) return differences; } } + + /// + /// Helper class to read the datasource for the image tests. The datasource will read the embedded resource with the Tests and will pass a + /// TestData class with the data to test. + /// + public class ImageTestDataSource + { + public class TestData + { + public string BasePath { get; set; } + public string BaseName { get; set; } + public override string ToString() + { + return $"TestDataSource - {BaseName}"; + } + } + + public static IEnumerable PassingTests() + { + var basePath = SuiteTestsFolder; + var testSuite = Path.Combine(basePath, "W3CTestSuite"); + var rows = new ImageTestDataSource().LoadRowsFromResourceCsv().Skip(1); //Skip header row + foreach (var row in rows) + yield return new TestData() { BasePath = testSuite, BaseName = row }; + } + + private const string ResourceIdentifier = "PassingTests.csv"; + /// + /// Read the rows from the resource + /// + /// + private string[] LoadRowsFromResourceCsv() + { + var assembly = typeof(ImageTestDataSource).Assembly; + string resourceName = assembly.GetManifestResourceNames().FirstOrDefault(r => r.IndexOf(ResourceIdentifier) > -1); + if(resourceName == null) { throw new Exception($"Cannot find data resource: {ResourceIdentifier}"); } + String res = ""; + using (Stream stream = assembly.GetManifestResourceStream(resourceName)) + { + using (StreamReader reader = new StreamReader(stream)) + { + res = reader.ReadToEnd(); + } + } + return res.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); + } + + private static string _basePath = null; + /// + /// Determine the folder the testsuite is running in. + /// + public static string SuiteTestsFolder + { + get + { + if (_basePath != null) return _basePath; + var basePath = Environment.CurrentDirectory; + while (!basePath.ToLower().EndsWith("svg")) + { + basePath = Path.GetDirectoryName(basePath); + } + + _basePath = Path.Combine(basePath, "Tests"); + return _basePath; + } + } + } } diff --git a/Tests/Svg.UnitTests/Svg.UnitTests.csproj b/Tests/Svg.UnitTests/Svg.UnitTests.csproj index 86f793489..15d77810d 100644 --- a/Tests/Svg.UnitTests/Svg.UnitTests.csproj +++ b/Tests/Svg.UnitTests/Svg.UnitTests.csproj @@ -26,8 +26,8 @@ - - + + From be859a4285d2c4557bf2f23843bb760009f5610b Mon Sep 17 00:00:00 2001 From: gvheertum-taxmodel Date: Wed, 19 Jun 2019 14:27:21 +0200 Subject: [PATCH 06/10] Spaces, no tabs ;) --- Tests/Svg.UnitTests/CssQueryTest.cs | 50 +++---- Tests/Svg.UnitTests/ImageComparisonTest.cs | 148 ++++++++++----------- Tests/Svg.UnitTests/LexerIssueTests.cs | 66 ++++----- 3 files changed, 132 insertions(+), 132 deletions(-) diff --git a/Tests/Svg.UnitTests/CssQueryTest.cs b/Tests/Svg.UnitTests/CssQueryTest.cs index 00216363a..50187d7ac 100644 --- a/Tests/Svg.UnitTests/CssQueryTest.cs +++ b/Tests/Svg.UnitTests/CssQueryTest.cs @@ -72,30 +72,30 @@ private void TestSelectorSpecificity(string selector, int specificity) /// ///Lifted from http://www.smashingmagazine.com/2007/07/27/css-specificity-things-you-should-know/, and http://css-tricks.com/specifics-on-css-specificity/ [Test] - [TestCase("*", 0x0)] - [TestCase("li", 0x10)] - [TestCase("li:first-line", 0x20)] - [TestCase("ul li", 0x20)] - [TestCase("ul ol+li", 0x30)] - [TestCase("h1 + *[rel=up]", 0x110)] - [TestCase("ul ol li.red", 0x130)] - [TestCase("li.red.level", 0x210)] - [TestCase("p", 0x010)] - [TestCase("div p", 0x020)] - [TestCase(".sith", 0x100)] - [TestCase("div p.sith", 0x120)] - [TestCase("#sith", 0x1000)] - [TestCase("body #darkside .sith p", 0x1120)] - [TestCase("body #content .data img:hover", 0x1220)] - [TestCase("a#a-02", 0x1010)] - [TestCase("a[id=\"a-02\"]", 0x0110)] - [TestCase("ul#nav li.active a", 0x1130)] - [TestCase("body.ie7 .col_3 h2 ~ h2", 0x0230)] - [TestCase("#footer *:not(nav) li", 0x1020)] - [TestCase("ul > li ul li ol li:first-letter", 0x0070)] - public void RunSpecificityTests(string selector, int specifity) - { - TestSelectorSpecificity(selector, specifity); - } + [TestCase("*", 0x0)] + [TestCase("li", 0x10)] + [TestCase("li:first-line", 0x20)] + [TestCase("ul li", 0x20)] + [TestCase("ul ol+li", 0x30)] + [TestCase("h1 + *[rel=up]", 0x110)] + [TestCase("ul ol li.red", 0x130)] + [TestCase("li.red.level", 0x210)] + [TestCase("p", 0x010)] + [TestCase("div p", 0x020)] + [TestCase(".sith", 0x100)] + [TestCase("div p.sith", 0x120)] + [TestCase("#sith", 0x1000)] + [TestCase("body #darkside .sith p", 0x1120)] + [TestCase("body #content .data img:hover", 0x1220)] + [TestCase("a#a-02", 0x1010)] + [TestCase("a[id=\"a-02\"]", 0x0110)] + [TestCase("ul#nav li.active a", 0x1130)] + [TestCase("body.ie7 .col_3 h2 ~ h2", 0x0230)] + [TestCase("#footer *:not(nav) li", 0x1020)] + [TestCase("ul > li ul li ol li:first-letter", 0x0070)] + public void RunSpecificityTests(string selector, int specifity) + { + TestSelectorSpecificity(selector, specifity); + } } } diff --git a/Tests/Svg.UnitTests/ImageComparisonTest.cs b/Tests/Svg.UnitTests/ImageComparisonTest.cs index c1a3d098a..f0ac6ae5f 100644 --- a/Tests/Svg.UnitTests/ImageComparisonTest.cs +++ b/Tests/Svg.UnitTests/ImageComparisonTest.cs @@ -18,7 +18,7 @@ public class ImageComparisonTest public TestContext TestContext { get; set; } #if NETCORE - /// + /// /// Compares SVG images against reference PNG images from the W3C SVG 1.1 test suite. /// This tests 158 out of 179 passing tests - the rest will not pass /// the test for several reasons. @@ -26,12 +26,12 @@ public class ImageComparisonTest /// so this is not a definitive test for image equality yet. /// [Test] - [TestCaseSource(typeof(ImageTestDataSource), nameof(ImageTestDataSource.PassingTests))] - public void CompareSvgImageWithReference(ImageTestDataSource.TestData testData) + [TestCaseSource(typeof(ImageTestDataSource), nameof(ImageTestDataSource.PassingTests))] + public void CompareSvgImageWithReference(ImageTestDataSource.TestData testData) { - string basePath = testData.BasePath; - string baseName = testData.BaseName; - bool testSaveLoad = !baseName.StartsWith("#"); + string basePath = testData.BasePath; + string baseName = testData.BaseName; + bool testSaveLoad = !baseName.StartsWith("#"); if (!testSaveLoad) { baseName = baseName.Substring(1); @@ -42,7 +42,7 @@ public void CompareSvgImageWithReference(ImageTestDataSource.TestData testData) } #else [Test] - [TestCaseSource(typeof(ImageTestDataSource), "PassingTests")] + [TestCaseSource(typeof(ImageTestDataSource), "PassingTests")] public void CompareSvgImageWithReference(ImageTestDataSource.TestData testData) { var basePath = testData.BasePath; @@ -64,7 +64,7 @@ public void CompareSvgImageWithReference(ImageTestDataSource.TestData testData) } #endif - private void CompareSvgImageWithReferenceImpl(string baseName, + private void CompareSvgImageWithReferenceImpl(string baseName, string svgPath, string pngPath, bool testSaveLoad) { var pngImage = Image.FromFile(pngPath); @@ -111,13 +111,13 @@ private void CompareSvgImageWithReferenceImpl(string baseName, public void RecordDiffForAllSvgImagesWithReference() { #if NETCORE - var basePath = Path.Combine(ImageTestDataSource.SuiteTestsFolder, "W3CTestSuite"); + var basePath = Path.Combine(ImageTestDataSource.SuiteTestsFolder, "W3CTestSuite"); #else var basePath = Path.GetDirectoryName(Path.GetDirectoryName(Path.GetDirectoryName(TestContext.TestDirectory))); //TODO: Tthe get dir name was parsed from the testparams -> Path.GetDirectoryName(Path.GetDirectoryName(Path.GetDirectoryName(TestContext.TestRunDirectory))); basePath = Path.Combine(Path.Combine(basePath, "Tests"), "W3CTestSuite"); #endif - // var svgBasePath = Path.Combine(basePath, "svg"); - string[] lines = File.ReadAllLines(@"..\..\..\..\Tests\Svg.UnitTests\all.csv"); + // var svgBasePath = Path.Combine(basePath, "svg"); + string[] lines = File.ReadAllLines(@"..\..\..\..\Tests\Svg.UnitTests\all.csv"); foreach (var baseName in lines) { var svgPath = Path.Combine(Path.Combine(basePath, "svg"), baseName + ".svg"); @@ -294,70 +294,70 @@ public static Image GetGrayScaleVersion(this Image original) } } - /// - /// Helper class to read the datasource for the image tests. The datasource will read the embedded resource with the Tests and will pass a - /// TestData class with the data to test. - /// - public class ImageTestDataSource - { - public class TestData - { - public string BasePath { get; set; } - public string BaseName { get; set; } - public override string ToString() - { - return $"TestDataSource - {BaseName}"; - } - } + /// + /// Helper class to read the datasource for the image tests. The datasource will read the embedded resource with the Tests and will pass a + /// TestData class with the data to test. + /// + public class ImageTestDataSource + { + public class TestData + { + public string BasePath { get; set; } + public string BaseName { get; set; } + public override string ToString() + { + return $"TestDataSource - {BaseName}"; + } + } - public static IEnumerable PassingTests() - { - var basePath = SuiteTestsFolder; - var testSuite = Path.Combine(basePath, "W3CTestSuite"); - var rows = new ImageTestDataSource().LoadRowsFromResourceCsv().Skip(1); //Skip header row - foreach (var row in rows) - yield return new TestData() { BasePath = testSuite, BaseName = row }; - } - - private const string ResourceIdentifier = "PassingTests.csv"; - /// - /// Read the rows from the resource - /// - /// - private string[] LoadRowsFromResourceCsv() - { - var assembly = typeof(ImageTestDataSource).Assembly; - string resourceName = assembly.GetManifestResourceNames().FirstOrDefault(r => r.IndexOf(ResourceIdentifier) > -1); - if(resourceName == null) { throw new Exception($"Cannot find data resource: {ResourceIdentifier}"); } - String res = ""; - using (Stream stream = assembly.GetManifestResourceStream(resourceName)) - { - using (StreamReader reader = new StreamReader(stream)) - { - res = reader.ReadToEnd(); - } - } - return res.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); - } + public static IEnumerable PassingTests() + { + var basePath = SuiteTestsFolder; + var testSuite = Path.Combine(basePath, "W3CTestSuite"); + var rows = new ImageTestDataSource().LoadRowsFromResourceCsv().Skip(1); //Skip header row + foreach (var row in rows) + yield return new TestData() { BasePath = testSuite, BaseName = row }; + } + + private const string ResourceIdentifier = "PassingTests.csv"; + /// + /// Read the rows from the resource + /// + /// + private string[] LoadRowsFromResourceCsv() + { + var assembly = typeof(ImageTestDataSource).Assembly; + string resourceName = assembly.GetManifestResourceNames().FirstOrDefault(r => r.IndexOf(ResourceIdentifier) > -1); + if(resourceName == null) { throw new Exception($"Cannot find data resource: {ResourceIdentifier}"); } + String res = ""; + using (Stream stream = assembly.GetManifestResourceStream(resourceName)) + { + using (StreamReader reader = new StreamReader(stream)) + { + res = reader.ReadToEnd(); + } + } + return res.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); + } - private static string _basePath = null; - /// - /// Determine the folder the testsuite is running in. - /// - public static string SuiteTestsFolder - { - get - { - if (_basePath != null) return _basePath; - var basePath = Environment.CurrentDirectory; - while (!basePath.ToLower().EndsWith("svg")) - { - basePath = Path.GetDirectoryName(basePath); - } + private static string _basePath = null; + /// + /// Determine the folder the testsuite is running in. + /// + public static string SuiteTestsFolder + { + get + { + if (_basePath != null) return _basePath; + var basePath = Environment.CurrentDirectory; + while (!basePath.ToLower().EndsWith("svg")) + { + basePath = Path.GetDirectoryName(basePath); + } - _basePath = Path.Combine(basePath, "Tests"); - return _basePath; - } - } - } + _basePath = Path.Combine(basePath, "Tests"); + return _basePath; + } + } + } } diff --git a/Tests/Svg.UnitTests/LexerIssueTests.cs b/Tests/Svg.UnitTests/LexerIssueTests.cs index 4699d9cb4..f96be9013 100644 --- a/Tests/Svg.UnitTests/LexerIssueTests.cs +++ b/Tests/Svg.UnitTests/LexerIssueTests.cs @@ -52,42 +52,42 @@ public void Lexer_NoImportantAndImportantAfterNonHex_Success(string testString) GenerateLexerTestFile(testString); } - [Test] - public void Lexer_FileWithValidHex_ColorTagIsIssued() - { - // valid colors - var doc = GenerateLexerTestFile("fill: #ff0000; stroke: #ffff00"); - var path = doc.GetElementById("path1"); - Assert.AreEqual(System.Drawing.Color.Red, ((SvgColourServer)path.Fill).Colour); - Assert.AreEqual(System.Drawing.Color.Yellow, ((SvgColourServer)path.Stroke).Colour); - } + [Test] + public void Lexer_FileWithValidHex_ColorTagIsIssued() + { + // valid colors + var doc = GenerateLexerTestFile("fill: #ff0000; stroke: #ffff00"); + var path = doc.GetElementById("path1"); + Assert.AreEqual(System.Drawing.Color.Red, ((SvgColourServer)path.Fill).Colour); + Assert.AreEqual(System.Drawing.Color.Yellow, ((SvgColourServer)path.Stroke).Colour); + } - [Test] - public void Lexer_FileWithInvalidHex_ColorTagOnlyReverstToDefaultForTheInvalidTag() - { - // invalid/valid color combinations - default color is used for each invalid color - var doc = GenerateLexerTestFile("fill: #ff00; stroke: #00ff00"); - var path = doc.GetElementById("path1"); - // default fill color is Black - Assert.AreEqual(System.Drawing.Color.Black, ((SvgColourServer)path.Fill).Colour); - Assert.AreEqual(System.Drawing.Color.Lime, ((SvgColourServer)path.Stroke).Colour); - } + [Test] + public void Lexer_FileWithInvalidHex_ColorTagOnlyReverstToDefaultForTheInvalidTag() + { + // invalid/valid color combinations - default color is used for each invalid color + var doc = GenerateLexerTestFile("fill: #ff00; stroke: #00ff00"); + var path = doc.GetElementById("path1"); + // default fill color is Black + Assert.AreEqual(System.Drawing.Color.Black, ((SvgColourServer)path.Fill).Colour); + Assert.AreEqual(System.Drawing.Color.Lime, ((SvgColourServer)path.Stroke).Colour); + } - [Test] - public void Lexer_FileWithInvalidHex_ColorTagResolvesToTransparent() - { - var doc = GenerateLexerTestFile("fill: #fff; stroke: 005577"); - var path = doc.GetElementById("path1"); - Assert.AreEqual(System.Drawing.Color.White, ((SvgColourServer)path.Fill).Colour); - // default stroke color is null (transparent) - Assert.IsNull(path.Stroke); - } + [Test] + public void Lexer_FileWithInvalidHex_ColorTagResolvesToTransparent() + { + var doc = GenerateLexerTestFile("fill: #fff; stroke: 005577"); + var path = doc.GetElementById("path1"); + Assert.AreEqual(System.Drawing.Color.White, ((SvgColourServer)path.Fill).Colour); + // default stroke color is null (transparent) + Assert.IsNull(path.Stroke); + } - [Test] - public void Lexer_FileWithInvalidHex_EmptyColorTagIsIgnored() - { - var doc = GenerateLexerTestFile("fill:; stroke: #00557;"); - var path = doc.GetElementById("path1"); + [Test] + public void Lexer_FileWithInvalidHex_EmptyColorTagIsIgnored() + { + var doc = GenerateLexerTestFile("fill:; stroke: #00557;"); + var path = doc.GetElementById("path1"); Assert.AreEqual(System.Drawing.Color.Black, ((SvgColourServer)path.Fill).Colour); Assert.IsNull(path.Stroke); } From 168986790cb7b3c4572d676df0d3605b39c023ad Mon Sep 17 00:00:00 2001 From: gvheertum-taxmodel Date: Wed, 19 Jun 2019 14:30:04 +0200 Subject: [PATCH 07/10] Testproperty removed (was commented) --- Tests/Svg.UnitTests/MetafileRenderingTest.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/Tests/Svg.UnitTests/MetafileRenderingTest.cs b/Tests/Svg.UnitTests/MetafileRenderingTest.cs index 32a603c96..e10f19a5a 100644 --- a/Tests/Svg.UnitTests/MetafileRenderingTest.cs +++ b/Tests/Svg.UnitTests/MetafileRenderingTest.cs @@ -23,8 +23,6 @@ public class MetafileRenderingTest : SvgTestHelper [Test] - //TODO: What does this one do? - //[TestProperty(name: "speed", value: "slow")] public void TestMetafileRendering() { LoadSvg(GetXMLDocFromResource()); From e39cf5bfc22ad75a9f990ce12009c6419f4453b4 Mon Sep 17 00:00:00 2001 From: Gertjan Date: Thu, 11 Jul 2019 12:33:59 +0200 Subject: [PATCH 08/10] Stylesheets do no longer need a check regarding Gdi+, there is as far as we know no GDI interaction here and we expect the code to have encountered GDI problems in prior blocks, for readability the check is removed. --- Source/SvgDocument.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/Source/SvgDocument.cs b/Source/SvgDocument.cs index 88ecc457e..11db48215 100644 --- a/Source/SvgDocument.cs +++ b/Source/SvgDocument.cs @@ -412,7 +412,6 @@ public static SvgDocument Open(string path) catch (Exception ex) { Trace.TraceWarning(ex.Message); - if (ExceptionCaughtIsGdiPlusRelated(ex)) { throw; } // GDI+ errors should be rethrown } } } From 6868fef55412f421a89898a9cffdec8423a45655 Mon Sep 17 00:00:00 2001 From: Gertjan Date: Thu, 11 Jul 2019 12:41:28 +0200 Subject: [PATCH 09/10] Updated the svg project to only include the mac package when building for netcoreapp2.2 (otherwise compile might fail due to the package not compatible with other frameworks). --- Source/Svg.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Svg.csproj b/Source/Svg.csproj index 9a68d206b..b239f77a3 100644 --- a/Source/Svg.csproj +++ b/Source/Svg.csproj @@ -125,9 +125,9 @@ - + --> From 6adb16623b3dcc74b3e3c32d09b33441146ef3d4 Mon Sep 17 00:00:00 2001 From: Gertjan Date: Thu, 11 Jul 2019 13:02:01 +0200 Subject: [PATCH 10/10] Changed the validation of GDI capabilities to a ensure call in the document.open(). Isolated the check to a construction of a matrix object (this will yield the gdi errors if applicable). Also added a static function to query the GDI+ capability. This should improve readability and performance of the code since we no longer check each exception in the document creation. The usage of the GDI+ can be documented in the wiki --- Source/SvgDocument.cs | 315 +++++++++++++++------------- Tests/Svg.UnitTests/GdiPlusTests.cs | 26 +++ 2 files changed, 196 insertions(+), 145 deletions(-) create mode 100644 Tests/Svg.UnitTests/GdiPlusTests.cs diff --git a/Source/SvgDocument.cs b/Source/SvgDocument.cs index 11db48215..03b24d347 100644 --- a/Source/SvgDocument.cs +++ b/Source/SvgDocument.cs @@ -175,6 +175,68 @@ public virtual TSvgElement GetElementById(string id) where TSvgElem return (this.GetElementById(id) as TSvgElement); } + /// + /// Validate whether the system has GDI+ capabilities (non Windows related). + /// + /// Boolean whether the system is capable of using GDI+ + public static bool SystemIsGdiPlusCapable() + { + try + { + EnsureSystemIsGdiPlusCapable(); + } + catch(SvgGdiPlusCannotBeLoadedException) + { + return false; + } + return true; + } + + /// + /// Ensure that the running system is GDI capable, if not this will yield a + /// SvgGdiPlusCannotBeLoadedException exception. + /// + public static void EnsureSystemIsGdiPlusCapable() + { + try + { + var matrix = new Matrix(0, 0, 0, 0, 0, 0); + } + // GDI+ loading errors will result in TypeInitializationExceptions, + // for readability we will catch and wrap the error + catch (Exception e) + { + if (ExceptionCaughtIsGdiPlusRelated(e)) + { + // Throw only the customized exception if we are sure GDI+ is causing the problem + throw new SvgGdiPlusCannotBeLoadedException(e); + } + //Ignore any other form of error + } + } + + /// + /// Check if the current exception or one of its children is the targeted GDI+ exception. + /// It can be hidden in one of the InnerExceptions, so we need to iterate over them. + /// + /// The exception to validate against the GDI+ check + private static bool ExceptionCaughtIsGdiPlusRelated(Exception e) + { + var currE = e; + int cnt = 0; // Keep track of depth to prevent endless-loops + while (currE != null && cnt < 10) + { + var typeException = currE as DllNotFoundException; + if (typeException?.Message?.LastIndexOf("libgdiplus", StringComparison.OrdinalIgnoreCase) > -1) + { + return true; + } + currE = currE.InnerException; + cnt++; + } + return false; + } + /// /// Opens the document at the specified path and loads the SVG contents. /// @@ -280,180 +342,143 @@ public static SvgDocument Open(string path) private static T Open(XmlReader reader) where T : SvgDocument, new() { - try - { - var elementStack = new Stack(); - bool elementEmpty; - SvgElement element = null; - SvgElement parent; - T svgDocument = null; - var elementFactory = new SvgElementFactory(); + EnsureSystemIsGdiPlusCapable(); //Validate whether the GDI+ can be loaded, this will yield an exception if not + var elementStack = new Stack(); + bool elementEmpty; + SvgElement element = null; + SvgElement parent; + T svgDocument = null; + var elementFactory = new SvgElementFactory(); - var styles = new List(); + var styles = new List(); - while (reader.Read()) + while (reader.Read()) + { + try { - try + switch (reader.NodeType) { - switch (reader.NodeType) - { - case XmlNodeType.Element: - // Does this element have a value or children - // (Must do this check here before we progress to another node) - elementEmpty = reader.IsEmptyElement; - // Create element - if (elementStack.Count > 0) - { - element = elementFactory.CreateElement(reader, svgDocument); - } - else - { - svgDocument = elementFactory.CreateDocument(reader); - element = svgDocument; - } + case XmlNodeType.Element: + // Does this element have a value or children + // (Must do this check here before we progress to another node) + elementEmpty = reader.IsEmptyElement; + // Create element + if (elementStack.Count > 0) + { + element = elementFactory.CreateElement(reader, svgDocument); + } + else + { + svgDocument = elementFactory.CreateDocument(reader); + element = svgDocument; + } - // Add to the parents children - if (elementStack.Count > 0) + // Add to the parents children + if (elementStack.Count > 0) + { + parent = elementStack.Peek(); + if (parent != null && element != null) { - parent = elementStack.Peek(); - if (parent != null && element != null) - { - parent.Children.Add(element); - parent.Nodes.Add(element); - } + parent.Children.Add(element); + parent.Nodes.Add(element); } + } - // Push element into stack - elementStack.Push(element); + // Push element into stack + elementStack.Push(element); - // Need to process if the element is empty - if (elementEmpty) - { - goto case XmlNodeType.EndElement; - } + // Need to process if the element is empty + if (elementEmpty) + { + goto case XmlNodeType.EndElement; + } - break; - case XmlNodeType.EndElement: + break; + case XmlNodeType.EndElement: - // Pop the element out of the stack - element = elementStack.Pop(); + // Pop the element out of the stack + element = elementStack.Pop(); - if (element.Nodes.OfType().Any()) - { - element.Content = (from e in element.Nodes select e.Content).Aggregate((p, c) => p + c); - } - else - { - element.Nodes.Clear(); // No sense wasting the space where it isn't needed - } + if (element.Nodes.OfType().Any()) + { + element.Content = (from e in element.Nodes select e.Content).Aggregate((p, c) => p + c); + } + else + { + element.Nodes.Clear(); // No sense wasting the space where it isn't needed + } - var unknown = element as SvgUnknownElement; - if (unknown != null && unknown.ElementName == "style") - { - styles.Add(unknown); - } - break; - case XmlNodeType.CDATA: - case XmlNodeType.Text: - element = elementStack.Peek(); - element.Nodes.Add(new SvgContentNode() { Content = reader.Value }); - break; - case XmlNodeType.EntityReference: - reader.ResolveEntity(); - element = elementStack.Peek(); - element.Nodes.Add(new SvgContentNode() { Content = reader.Value }); - break; - } - } - catch (Exception exc) - { - Trace.TraceError(exc.Message); - if (ExceptionCaughtIsGdiPlusRelated(exc)) { throw; } // GDI+ errors should be rethrown + var unknown = element as SvgUnknownElement; + if (unknown != null && unknown.ElementName == "style") + { + styles.Add(unknown); + } + break; + case XmlNodeType.CDATA: + case XmlNodeType.Text: + element = elementStack.Peek(); + element.Nodes.Add(new SvgContentNode() { Content = reader.Value }); + break; + case XmlNodeType.EntityReference: + reader.ResolveEntity(); + element = elementStack.Peek(); + element.Nodes.Add(new SvgContentNode() { Content = reader.Value }); + break; } } + catch (Exception exc) + { + Trace.TraceError(exc.Message); + } + } - if (styles.Any()) + if (styles.Any()) + { + var cssTotal = styles.Select((s) => s.Content).Aggregate((p, c) => p + Environment.NewLine + c); + var cssParser = new Parser(); + var sheet = cssParser.Parse(cssTotal); + AggregateSelectorList aggList; + IEnumerable selectors; + IEnumerable elemsToStyle; + + foreach (var rule in sheet.StyleRules) { - var cssTotal = styles.Select((s) => s.Content).Aggregate((p, c) => p + Environment.NewLine + c); - var cssParser = new Parser(); - var sheet = cssParser.Parse(cssTotal); - AggregateSelectorList aggList; - IEnumerable selectors; - IEnumerable elemsToStyle; - - foreach (var rule in sheet.StyleRules) + aggList = rule.Selector as AggregateSelectorList; + if (aggList != null && aggList.Delimiter == ",") { - aggList = rule.Selector as AggregateSelectorList; - if (aggList != null && aggList.Delimiter == ",") - { - selectors = aggList; - } - else - { - selectors = Enumerable.Repeat(rule.Selector, 1); - } + selectors = aggList; + } + else + { + selectors = Enumerable.Repeat(rule.Selector, 1); + } - foreach (var selector in selectors) + foreach (var selector in selectors) + { + try { - try - { - var rootNode = new NonSvgElement(); - rootNode.Children.Add(svgDocument); + var rootNode = new NonSvgElement(); + rootNode.Children.Add(svgDocument); - elemsToStyle = rootNode.QuerySelectorAll(rule.Selector.ToString(), elementFactory); - foreach (var elem in elemsToStyle) + elemsToStyle = rootNode.QuerySelectorAll(rule.Selector.ToString(), elementFactory); + foreach (var elem in elemsToStyle) + { + foreach (var decl in rule.Declarations) { - foreach (var decl in rule.Declarations) - { - elem.AddStyle(decl.Name, decl.Term.ToString(), rule.Selector.GetSpecificity()); - } + elem.AddStyle(decl.Name, decl.Term.ToString(), rule.Selector.GetSpecificity()); } } - catch (Exception ex) - { - Trace.TraceWarning(ex.Message); - } + } + catch (Exception ex) + { + Trace.TraceWarning(ex.Message); } } } - - if (svgDocument != null) FlushStyles(svgDocument); - return svgDocument; } - // GDI+ loading errors will result in TypeInitializationExceptions, - // for readability we will catch and wrap the error - catch (Exception e) - { - if (ExceptionCaughtIsGdiPlusRelated(e)) - { - // Throw only the customized exception if we are sure GDI+ is causing the problem - throw new SvgGdiPlusCannotBeLoadedException(e); - } - // No wrapping, just rethrow the exception - throw; - } - } - /// - /// Check if the current exception or one of its children is the targeted GDI+ exception. - /// It can be hidden in one of the InnerExceptions, so we need to iterate over them. - /// - /// The exception to validate against the GDI+ check - private static bool ExceptionCaughtIsGdiPlusRelated(Exception e) - { - var currE = e; - int cnt = 0; // Keep track of depth to prevent endless-loops - while (currE != null && cnt < 10) - { - var typeException = currE as DllNotFoundException; - if (typeException?.Message?.LastIndexOf("libgdiplus", StringComparison.OrdinalIgnoreCase) > -1) - { - return true; - } - currE = currE.InnerException; - cnt++; - } - return false; + if (svgDocument != null) FlushStyles(svgDocument); + return svgDocument; } private static void FlushStyles(SvgElement elem) diff --git a/Tests/Svg.UnitTests/GdiPlusTests.cs b/Tests/Svg.UnitTests/GdiPlusTests.cs new file mode 100644 index 000000000..fac02ad7b --- /dev/null +++ b/Tests/Svg.UnitTests/GdiPlusTests.cs @@ -0,0 +1,26 @@ +using NUnit.Framework; + +namespace Svg.UnitTests +{ + + /// + /// Simple testing of the GDI+ capabilities, just to ensure whether the checks are inmplemented correctly + /// + [TestFixture] + public class GdiPlusTests : SvgTestHelper + { + [Test] + public void GdiPlus_QueryCapability_YieldsTrue() + { + Assert.True(SvgDocument.SystemIsGdiPlusCapable(), "The gdiplus check should yield true, please validate gdi+ capabilities"); + } + + [Test] + public void GdiPlus_EnsureCapability_YieldsNoError() + { + SvgDocument.EnsureSystemIsGdiPlusCapable(); + //This should not cause problems + } + + } +} \ No newline at end of file