From db66fc40cf5e2b250a44869effec37ff51d5ade1 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Tue, 18 Jul 2017 12:43:56 -0400 Subject: [PATCH 1/6] Resurrecting old unit tests --- .../Collections/IcdHashSetTest.cs | 161 +++++++++++++++++ .../Collections/ScrollQueueTest.cs | 80 +++++++++ ICD.Common.Utils.Tests/MathUtilsTest.cs | 37 ++++ ICD.Common.Utils.Tests/PathUtilsTest.cs | 25 +++ ICD.Common.Utils.Tests/StringUtilsTest.cs | 82 +++++++++ .../Xml/IcdXmlAttributeTest.cs | 17 ++ ICD.Common.Utils.Tests/Xml/XmlUtilsTest.cs | 164 ++++++++++++++++++ 7 files changed, 566 insertions(+) create mode 100644 ICD.Common.Utils.Tests/Collections/IcdHashSetTest.cs create mode 100644 ICD.Common.Utils.Tests/Collections/ScrollQueueTest.cs create mode 100644 ICD.Common.Utils.Tests/MathUtilsTest.cs create mode 100644 ICD.Common.Utils.Tests/PathUtilsTest.cs create mode 100644 ICD.Common.Utils.Tests/StringUtilsTest.cs create mode 100644 ICD.Common.Utils.Tests/Xml/IcdXmlAttributeTest.cs create mode 100644 ICD.Common.Utils.Tests/Xml/XmlUtilsTest.cs diff --git a/ICD.Common.Utils.Tests/Collections/IcdHashSetTest.cs b/ICD.Common.Utils.Tests/Collections/IcdHashSetTest.cs new file mode 100644 index 0000000..831a6b4 --- /dev/null +++ b/ICD.Common.Utils.Tests/Collections/IcdHashSetTest.cs @@ -0,0 +1,161 @@ +using System; +using NUnit.Framework; +using ICD.Common.Properties; +using ICD.Common.Utils.Collections; + +namespace Icd.Common.Utils.Tests.Collections +{ + [TestFixture] + public sealed class IcdHashSetTest + { + [Test, UsedImplicitly] + public void NullSetTest() + { + Assert.AreEqual(0, IcdHashSet.NullSet.Count); + } + + [Test, UsedImplicitly] + public void CountTest() + { + Assert.AreEqual(3, new IcdHashSet(new[] {1, 2, 2, 3}).Count); + } + + [Test, UsedImplicitly] + public void AddTest() + { + IcdHashSet set = new IcdHashSet(); + + Assert.IsTrue(set.Add("One")); + Assert.IsFalse(set.Add("One")); + + Assert.Throws(() => set.Add(null)); + } + + [Test, UsedImplicitly] + public void AddRangeTest() + { + IcdHashSet set = new IcdHashSet(); + + set.AddRange(new []{1, 2, 2, 3}); + + Assert.AreEqual(3, set.Count); + } + + [Test, UsedImplicitly] + public void ClearTest() + { + IcdHashSet set = new IcdHashSet(new[] {1, 2, 2, 3}); + set.Clear(); + + Assert.AreEqual(0, set.Count); + } + + [Test, UsedImplicitly] + public void ContainsTest() + { + IcdHashSet set = new IcdHashSet(new[] { 1, 2, 2, 3 }); + + Assert.IsTrue(set.Contains(1)); + Assert.IsTrue(set.Contains(2)); + Assert.IsTrue(set.Contains(3)); + Assert.IsFalse(set.Contains(4)); + } + + [Test, UsedImplicitly] + public void RemoveTest() + { + IcdHashSet set = new IcdHashSet(new[] { 1, 2, 2, 3 }); + set.Remove(2); + + Assert.IsFalse(set.Contains(2)); + } + + [Test, UsedImplicitly] + public void UnionTest() + { + IcdHashSet one = new IcdHashSet(new[] { 1, 2 }); + IcdHashSet two = new IcdHashSet(new[] { 2, 3 }); + IcdHashSet union = one.Union(two); + + Assert.AreEqual(3, union.Count); + } + + [Test, UsedImplicitly] + public void SubtractTest() + { + IcdHashSet one = new IcdHashSet(new[] { 1, 2 }); + IcdHashSet two = new IcdHashSet(new[] { 2, 3 }); + IcdHashSet subtract = one.Subtract(two); + + Assert.AreEqual(1, subtract.Count); + Assert.IsTrue(subtract.Contains(1)); + } + + [Test, UsedImplicitly] + public void IsSubsetOfTest() + { + IcdHashSet one = new IcdHashSet(new[] { 1, 2 }); + IcdHashSet two = new IcdHashSet(new[] { 2, 3 }); + IcdHashSet three = new IcdHashSet(new[] { 1, 2, 3 }); + + Assert.IsFalse(one.IsSubsetOf(two)); + Assert.IsTrue(one.IsSubsetOf(three)); + } + + [Test, UsedImplicitly] + public void IntersectionTest() + { + IcdHashSet one = new IcdHashSet(new[] { 1, 2 }); + IcdHashSet two = new IcdHashSet(new[] { 2, 3 }); + IcdHashSet intersection = one.Intersection(two); + + Assert.AreEqual(1, intersection.Count); + Assert.IsTrue(intersection.Contains(2)); + } + + [Test, UsedImplicitly] + public void NonIntersectionTest() + { + IcdHashSet one = new IcdHashSet(new[] { 1, 2 }); + IcdHashSet two = new IcdHashSet(new[] { 2, 3 }); + IcdHashSet nonIntersection = one.NonIntersection(two); + + Assert.AreEqual(2, nonIntersection.Count); + Assert.IsTrue(nonIntersection.Contains(1)); + Assert.IsTrue(nonIntersection.Contains(3)); + } + + [Test, UsedImplicitly] + public void IsProperSubsetOfTest() + { + IcdHashSet one = new IcdHashSet(new[] { 1, 2 }); + IcdHashSet two = new IcdHashSet(new[] { 1, 2 }); + IcdHashSet three = new IcdHashSet(new[] { 1, 2, 3 }); + + Assert.IsFalse(one.IsProperSubsetOf(two)); + Assert.IsTrue(one.IsProperSubsetOf(three)); + } + + [Test, UsedImplicitly] + public void IsSupersetOfTest() + { + IcdHashSet one = new IcdHashSet(new[] { 1, 2 }); + IcdHashSet two = new IcdHashSet(new[] { 2, 3 }); + IcdHashSet three = new IcdHashSet(new[] { 1, 2, 3 }); + + Assert.IsFalse(two.IsSupersetOf(one)); + Assert.IsTrue(three.IsSupersetOf(one)); + } + + [Test, UsedImplicitly] + public void IsProperSupersetOfTest() + { + IcdHashSet one = new IcdHashSet(new[] { 1, 2 }); + IcdHashSet two = new IcdHashSet(new[] { 1, 2 }); + IcdHashSet three = new IcdHashSet(new[] { 1, 2, 3 }); + + Assert.IsFalse(two.IsProperSupersetOf(one)); + Assert.IsTrue(three.IsProperSupersetOf(one)); + } + } +} \ No newline at end of file diff --git a/ICD.Common.Utils.Tests/Collections/ScrollQueueTest.cs b/ICD.Common.Utils.Tests/Collections/ScrollQueueTest.cs new file mode 100644 index 0000000..bf5e7a2 --- /dev/null +++ b/ICD.Common.Utils.Tests/Collections/ScrollQueueTest.cs @@ -0,0 +1,80 @@ +using System.Linq; +using NUnit.Framework; +using ICD.Common.Properties; +using ICD.Common.Utils.Collections; + +namespace ICD.Common.Utils.Tests.Collections +{ + [TestFixture] + public sealed class ScrollQueueTest + { + [Test, UsedImplicitly] + public void MaxSizeTest() + { + ScrollQueue test = new ScrollQueue(5); + test.Enqueue(0); + test.Enqueue(1); + test.Enqueue(2); + test.Enqueue(3); + test.Enqueue(4); + + Assert.AreEqual(5, test.Count); + + test.MaxSize = 3; + + Assert.AreEqual(3, test.Count); + Assert.AreEqual(2, test.Peek()); + + test.Enqueue(0); + + Assert.AreEqual(3, test.Count); + Assert.AreEqual(3, test.Peek()); + } + + [Test, UsedImplicitly] + public void ClearTest() + { + ScrollQueue test = new ScrollQueue(5); + test.Enqueue(0); + test.Clear(); + + Assert.AreEqual(0, test.Count); + } + + [Test, UsedImplicitly] + public void EnqueueTest() + { + ScrollQueue test = new ScrollQueue(5); + test.Enqueue(0); + test.Enqueue(1); + + Assert.AreEqual(2, test.Count); + + int[] array = test.ToArray(); + + Assert.AreEqual(0, array[0]); + Assert.AreEqual(1, array[1]); + } + + [Test, UsedImplicitly] + public void DequeueTest() + { + ScrollQueue test = new ScrollQueue(5); + test.Enqueue(0); + test.Enqueue(1); + + Assert.AreEqual(0, test.Dequeue()); + Assert.AreEqual(1, test.Count); + } + + [Test, UsedImplicitly] + public void PeekTest() + { + ScrollQueue test = new ScrollQueue(5); + test.Enqueue(0); + test.Enqueue(1); + + Assert.AreEqual(0, test.Peek()); + } + } +} \ No newline at end of file diff --git a/ICD.Common.Utils.Tests/MathUtilsTest.cs b/ICD.Common.Utils.Tests/MathUtilsTest.cs new file mode 100644 index 0000000..2e3a76f --- /dev/null +++ b/ICD.Common.Utils.Tests/MathUtilsTest.cs @@ -0,0 +1,37 @@ +using ICD.Common.Properties; +using NUnit.Framework; + +namespace ICD.Common.Utils.Tests +{ + [TestFixture] + public sealed class MathUtilsTest + { + [Test, UsedImplicitly] + public void ClampTest() + { + Assert.AreEqual(MathUtils.Clamp(-10, 0, 0), 0); + Assert.AreEqual(MathUtils.Clamp(-10, 10, 0), 0); + Assert.AreEqual(MathUtils.Clamp(-10, 0, 10), 0); + + Assert.AreEqual(MathUtils.Clamp(0, 0, 0), 0); + Assert.AreEqual(MathUtils.Clamp(0, 10, 0), 0); + Assert.AreEqual(MathUtils.Clamp(0, 0, 10), 0); + + Assert.AreEqual(MathUtils.Clamp(20, 0, 10), 10); + Assert.AreEqual(MathUtils.Clamp(20, 10, 0), 10); + Assert.AreEqual(MathUtils.Clamp(20, 10, 10), 10); + } + + [Test, UsedImplicitly] + public void MapRangeTest() + { + Assert.AreEqual(0, MathUtils.MapRange(0, 100, 0, 10, 0)); + Assert.AreEqual(5, MathUtils.MapRange(0, 100, 0, 10, 50)); + Assert.AreEqual(10, MathUtils.MapRange(0, 100, 0, 10, 100)); + + Assert.AreEqual(0, MathUtils.MapRange(0, 10, 0, 100, 0)); + Assert.AreEqual(50, MathUtils.MapRange(0, 10, 0, 100, 5)); + Assert.AreEqual(100, MathUtils.MapRange(0, 10, 0, 100, 10)); + } + } +} diff --git a/ICD.Common.Utils.Tests/PathUtilsTest.cs b/ICD.Common.Utils.Tests/PathUtilsTest.cs new file mode 100644 index 0000000..36fc190 --- /dev/null +++ b/ICD.Common.Utils.Tests/PathUtilsTest.cs @@ -0,0 +1,25 @@ +using System.Linq; +using NUnit.Framework; +using ICD.Common.Utils; +using ICD.Common.Properties; +#if SIMPLSHARP +using Crestron.IO; +#else +using System.IO; +#endif + +namespace RSD.SimplSharp.Common.Interfaces.Tests.Utils +{ + [TestFixture] + public sealed class PathUtilsTest + { + [Test, UsedImplicitly] + public void JoinTest() + { + string expected = Path.Combine("A", "B"); + expected = Path.Combine(expected, "C"); + + Assert.AreEqual(expected, PathUtils.Join("A", "B", "C")); + } + } +} diff --git a/ICD.Common.Utils.Tests/StringUtilsTest.cs b/ICD.Common.Utils.Tests/StringUtilsTest.cs new file mode 100644 index 0000000..070aab9 --- /dev/null +++ b/ICD.Common.Utils.Tests/StringUtilsTest.cs @@ -0,0 +1,82 @@ +using ICD.Common.Properties; +using NUnit.Framework; + +namespace ICD.Common.Utils.Tests +{ + [TestFixture] + public sealed class StringUtilsTest + { + [Test, UsedImplicitly] + public void ToHexLiteralTest() + { + const string hex = "\x08\x22\x00\x00\x00\x02"; + string output = StringUtils.ToHexLiteral(hex); + + Assert.AreEqual(@"\x08\x22\x00\x00\x00\x02", output); + } + + [Test, UsedImplicitly] + public void FromHexLiteralTest() + { + const string literal = @"\x08\x22\x00\x00\x00\x02"; + string output = StringUtils.FromHexLiteral(literal); + + Assert.AreEqual("\x08\x22\x00\x00\x00\x02", output); + } + + [Test, UsedImplicitly] + public void NiceNameTest() + { + string output = StringUtils.NiceName("TodayILiveInTheUSAWithSimon"); + Assert.AreEqual("Today I Live In The USA With Simon", output); + } + + [Test, UsedImplicitly] + public void SafeNumericFormatTest() + { + Assert.AreEqual(string.Empty, StringUtils.SafeNumericFormat("# # ###.###.####", string.Empty)); + Assert.AreEqual("9 1 252.943.4324", StringUtils.SafeNumericFormat("# # ###.###.####", "0000912529434324")); + Assert.AreEqual("9 1 252.943.4324", StringUtils.SafeNumericFormat("# # ###.###.####", "912529434324")); + Assert.AreEqual("1 252.943.4324", StringUtils.SafeNumericFormat("# # ###.###.####", "12529434324")); + Assert.AreEqual("252.943.4324", StringUtils.SafeNumericFormat("# # ###.###.####", "2529434324")); + Assert.AreEqual("052.943.4324", StringUtils.SafeNumericFormat("# # ###.###.####", "0529434324")); + } + + [Test, UsedImplicitly] + public void ReverseTest() + { + Assert.AreEqual("rabooF", StringUtils.Reverse("Foobar")); + } + + [Test, UsedImplicitly] + public void ArrayFormatTest() + { + int[] items = {1, 4, 3, 2, 5}; + Assert.AreEqual("[1, 4, 3, 2, 5]", StringUtils.ArrayFormat(items)); + } + + [Test, UsedImplicitly] + public void RangeFormatTest() + { + Assert.AreEqual("[-3 - 5]", StringUtils.RangeFormat(-3, 5)); + } + + [Test, UsedImplicitly] + public void UppercaseFirstTest() + { + Assert.AreEqual("Foobar", StringUtils.UppercaseFirst("foobar")); + } + + [Test, UsedImplicitly] + public void ToIpIdStringTest() + { + Assert.AreEqual("0x67", StringUtils.ToIpIdString(0x67)); + } + + [Test, UsedImplicitly] + public void FromIpIdStringTest() + { + Assert.AreEqual(0x67, StringUtils.FromIpIdString("0x67")); + } + } +} diff --git a/ICD.Common.Utils.Tests/Xml/IcdXmlAttributeTest.cs b/ICD.Common.Utils.Tests/Xml/IcdXmlAttributeTest.cs new file mode 100644 index 0000000..e3952bd --- /dev/null +++ b/ICD.Common.Utils.Tests/Xml/IcdXmlAttributeTest.cs @@ -0,0 +1,17 @@ +using ICD.Common.Properties; +using ICD.Common.Utils.Xml; +using NUnit.Framework; + +namespace ICD.Common.Utils.Tests.Xml +{ + [TestFixture] + public sealed class IcdXmlAttributeTest + { + [Test, UsedImplicitly] + public void ValueAsIntTest() + { + IcdXmlAttribute attribute = new IcdXmlAttribute("test", "12"); + Assert.AreEqual("12", attribute.Value); + } + } +} \ No newline at end of file diff --git a/ICD.Common.Utils.Tests/Xml/XmlUtilsTest.cs b/ICD.Common.Utils.Tests/Xml/XmlUtilsTest.cs new file mode 100644 index 0000000..3653c1c --- /dev/null +++ b/ICD.Common.Utils.Tests/Xml/XmlUtilsTest.cs @@ -0,0 +1,164 @@ +using System.Collections.Generic; +using System.Linq; +using NUnit.Framework; +using ICD.Common.Properties; +using ICD.Common.Utils.Xml; +#if SIMPLSHARP +using Crestron.Xml; +#else +using System.Xml; +#endif + +namespace ICD.Common.Utils.Tests.Xml +{ + [TestFixture] + public sealed class XmlUtilsTest + { + // Whitespace is important for testing Insignificant Whitespace nodes. + private const string EXAMPLE_XML = " " + + " " + + " " + + " " + + " Some text " + + " " + + " "; + + // For testing empty elements + private const string EXAMPLE_XML_2 = "" + + "" + + "" + + ""; + + [Test, UsedImplicitly] + public void GetAttributesTest() + { + using (IcdXmlReader reader = new IcdXmlReader(EXAMPLE_XML)) + { + reader.SkipToNextElement(); + + IcdXmlAttribute[] attributes = reader.GetAttributes().ToArray(); + + Assert.AreEqual(2, attributes.Length); + Assert.AreEqual("attr1", attributes[0].Name); + Assert.AreEqual("1", attributes[0].Value); + Assert.AreEqual("attr2", attributes[1].Name); + Assert.AreEqual("2", attributes[1].Value); + } + } + + [Test, UsedImplicitly] + public void GetAttributeAsIntTest() + { + using (IcdXmlReader reader = new IcdXmlReader(EXAMPLE_XML)) + { + reader.SkipToNextElement(); + + int value = reader.GetAttributeAsInt("attr1"); + Assert.AreEqual(1, value); + } + } + + [Test, UsedImplicitly] + public void RecursionTest() + { + List paths = new List(); + List nodes = new List(); + + XmlUtils.Recurse(EXAMPLE_XML, args => + { + paths.Add(args.Path); + nodes.Add(args.Outer); + } + ); + + Assert.AreEqual(4, paths.Count); + + Assert.AreEqual("Level1", paths[0][0]); + Assert.AreEqual("Level2", paths[1][1]); + Assert.AreEqual("Level2", paths[2][1]); + Assert.AreEqual("Level3", paths[3][2]); + + using (IcdXmlReader reader = new IcdXmlReader(nodes[3])) + { + reader.SkipToNextElement(); + Assert.AreEqual("Some text", reader.ReadInnerXml()); + } + } + + [Test, UsedImplicitly] + public void SkipInsignificantWhitespaceTest() + { + using (IcdXmlReader reader = new IcdXmlReader(EXAMPLE_XML)) + { + reader.Read(); + Assert.AreEqual(reader.NodeType, XmlNodeType.Whitespace); + + reader.SkipInsignificantWhitespace(); + Assert.AreNotEqual(reader.NodeType, XmlNodeType.Whitespace); + } + } + + [Test, UsedImplicitly] + public void SkipToNextElementTest() + { + using (IcdXmlReader reader = new IcdXmlReader(EXAMPLE_XML)) + { + reader.SkipToNextElement(); + Assert.AreEqual("Level1", reader.Name); + + reader.SkipToNextElement(); + Assert.AreEqual("Level2", reader.Name); + } + } + + [Test, UsedImplicitly] + public void GetChildElementsFromXmlTest() + { + IEnumerable results = XmlUtils.GetChildElements(EXAMPLE_XML); + IcdXmlReader[] children = results.ToArray(); + + Assert.AreEqual(2, children.Length); + Assert.AreEqual("Level2", children[0].Name); + Assert.AreEqual("Level2", children[1].Name); + + foreach (IcdXmlReader child in children) + child.Dispose(); + } + + [Test, UsedImplicitly] + public void GetChildElementsAsStringEmptyElementTest() + { + string[] results = XmlUtils.GetChildElementsAsString(EXAMPLE_XML_2).ToArray(); + + Assert.AreEqual(2, results.Length); + Assert.AreEqual("", results[0]); + Assert.AreEqual("", results[1]); + } + + [Test, UsedImplicitly] + public void GetChildElementsTest() + { + using (IcdXmlReader reader = new IcdXmlReader(EXAMPLE_XML)) + { + reader.SkipToNextElement(); + + IEnumerable results = reader.GetChildElements(); + IcdXmlReader[] children = results.ToArray(); + + Assert.AreEqual(2, children.Length); + Assert.AreEqual("Level2", children[0].Name); + Assert.AreEqual("Level2", children[1].Name); + + foreach (IcdXmlReader child in children) + child.Dispose(); + } + } + + [Test, UsedImplicitly] + public void IsValidXmlTest() + { + Assert.IsFalse(XmlUtils.IsValidXml(@"")); + Assert.IsTrue(XmlUtils.IsValidXml(EXAMPLE_XML)); + } + } +} \ No newline at end of file From 201e0878c763a9ecf3d46f0568bc965d985a6e27 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Tue, 18 Jul 2017 12:46:27 -0400 Subject: [PATCH 2/6] Optimization in adding multiple items to an IcdHashSet --- ICD.Common.Utils/Collections/IcdHashSet.cs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/ICD.Common.Utils/Collections/IcdHashSet.cs b/ICD.Common.Utils/Collections/IcdHashSet.cs index e1d9fa2..8561c70 100644 --- a/ICD.Common.Utils/Collections/IcdHashSet.cs +++ b/ICD.Common.Utils/Collections/IcdHashSet.cs @@ -192,8 +192,19 @@ namespace ICD.Common.Utils.Collections /// public void AddRange(IEnumerable items) { + if (items == null) + throw new ArgumentNullException("items"); + foreach (T item in items) - Add(item); + { + // ReSharper disable CompareNonConstrainedGenericWithNull + if (item == null) + // ReSharper restore CompareNonConstrainedGenericWithNull + throw new InvalidOperationException("item"); + + if (!m_Dict.ContainsKey(item)) + m_Dict[item] = null; + } } /// From 79621dcfda019c3b1dfa2ca5885b18d8710ed1bf Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Thu, 20 Jul 2017 13:05:34 -0400 Subject: [PATCH 3/6] Better exception when an attribute does not exist --- ICD.Common.Utils/Xml/XmlUtils.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ICD.Common.Utils/Xml/XmlUtils.cs b/ICD.Common.Utils/Xml/XmlUtils.cs index 5196045..bba7bdc 100644 --- a/ICD.Common.Utils/Xml/XmlUtils.cs +++ b/ICD.Common.Utils/Xml/XmlUtils.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Text; using ICD.Common.EventArguments; using ICD.Common.Properties; +using ICD.Common.Utils.Extensions; using ICD.Common.Utils.IO; namespace ICD.Common.Utils.Xml @@ -67,7 +68,11 @@ namespace ICD.Common.Utils.Xml [PublicAPI] public static IcdXmlAttribute GetAttribute(string xml, string name) { - return GetAttributes(xml).First(a => a.Name == name); + IcdXmlAttribute output; + if (GetAttributes(xml).TryFirstOrDefault(a => a.Name == name, out output)) + return output; + + throw new KeyNotFoundException(string.Format("No attribute with name {0}", name)); } /// From 71b3c5ad2a577756bbcef3220effcb90c80f211b Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Thu, 20 Jul 2017 13:06:00 -0400 Subject: [PATCH 4/6] Better name for TryFirst extension method --- ICD.Common.Utils/Extensions/EnumerableExtensions.cs | 6 +++--- ICD.Common.Utils/Xml/XmlUtils.cs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ICD.Common.Utils/Extensions/EnumerableExtensions.cs b/ICD.Common.Utils/Extensions/EnumerableExtensions.cs index 80e23df..66cc2bd 100644 --- a/ICD.Common.Utils/Extensions/EnumerableExtensions.cs +++ b/ICD.Common.Utils/Extensions/EnumerableExtensions.cs @@ -53,12 +53,12 @@ namespace ICD.Common.Utils.Extensions /// /// Outputs the first item in the sequence. /// - public static bool TryFirstOrDefault(this IEnumerable extends, out T item) + public static bool TryFirst(this IEnumerable extends, out T item) { if (extends == null) throw new ArgumentNullException("extends"); - return extends.TryFirstOrDefault(i => true, out item); + return extends.TryFirst(i => true, out item); } /// @@ -69,7 +69,7 @@ namespace ICD.Common.Utils.Extensions /// /// Outputs the first item in the sequence. /// - public static bool TryFirstOrDefault(this IEnumerable extends, Func predicate, out T item) + public static bool TryFirst(this IEnumerable extends, Func predicate, out T item) { if (extends == null) throw new ArgumentNullException("extends"); diff --git a/ICD.Common.Utils/Xml/XmlUtils.cs b/ICD.Common.Utils/Xml/XmlUtils.cs index bba7bdc..4a224dd 100644 --- a/ICD.Common.Utils/Xml/XmlUtils.cs +++ b/ICD.Common.Utils/Xml/XmlUtils.cs @@ -69,7 +69,7 @@ namespace ICD.Common.Utils.Xml public static IcdXmlAttribute GetAttribute(string xml, string name) { IcdXmlAttribute output; - if (GetAttributes(xml).TryFirstOrDefault(a => a.Name == name, out output)) + if (GetAttributes(xml).TryFirst(a => a.Name == name, out output)) return output; throw new KeyNotFoundException(string.Format("No attribute with name {0}", name)); From 442bd20759fcdd305f4f27bc29f128c1f7937d87 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Fri, 21 Jul 2017 09:52:46 -0400 Subject: [PATCH 5/6] Adding list extension methods for adding items to a sorted list --- .../Extensions/ListExtensionsTest.cs | 54 +++++++++++++++ ICD.Common.Utils/Extensions/ListExtensions.cs | 68 +++++++++++++++++++ .../ICD.Common.Utils_SimplSharp.csproj | 1 + 3 files changed, 123 insertions(+) create mode 100644 ICD.Common.Utils.Tests/Extensions/ListExtensionsTest.cs create mode 100644 ICD.Common.Utils/Extensions/ListExtensions.cs diff --git a/ICD.Common.Utils.Tests/Extensions/ListExtensionsTest.cs b/ICD.Common.Utils.Tests/Extensions/ListExtensionsTest.cs new file mode 100644 index 0000000..f05539c --- /dev/null +++ b/ICD.Common.Utils.Tests/Extensions/ListExtensionsTest.cs @@ -0,0 +1,54 @@ +using ICD.Common.Utils.Extensions; +using NUnit.Framework; +using System.Collections.Generic; +using System; + +namespace ICD.Common.Utils.Tests_NetStandard.Extensions +{ + [TestFixture] + public sealed class ListExtensionsTest + { + [Test] + public void AddSortedTest() + { + List testList = new List(); + + testList.AddSorted(2); + testList.AddSorted(3); + testList.AddSorted(1); + testList.AddSorted(2); + + Assert.AreEqual(4, testList.Count); + Assert.AreEqual(1, testList[0]); + Assert.AreEqual(2, testList[1]); + Assert.AreEqual(2, testList[2]); + Assert.AreEqual(3, testList[3]); + } + + [Test] + public void AddSortedComparerTest() + { + List testList = new List(); + IComparer comparer = new InverseComparer(); + + testList.AddSorted(2, comparer); + testList.AddSorted(3, comparer); + testList.AddSorted(1, comparer); + testList.AddSorted(2, comparer); + + Assert.AreEqual(4, testList.Count); + Assert.AreEqual(3, testList[0]); + Assert.AreEqual(2, testList[1]); + Assert.AreEqual(2, testList[2]); + Assert.AreEqual(1, testList[3]); + } + + internal class InverseComparer : IComparer + { + public int Compare(int x, int y) + { + return y.CompareTo(x); + } + } + } +} diff --git a/ICD.Common.Utils/Extensions/ListExtensions.cs b/ICD.Common.Utils/Extensions/ListExtensions.cs new file mode 100644 index 0000000..6cfe6ed --- /dev/null +++ b/ICD.Common.Utils/Extensions/ListExtensions.cs @@ -0,0 +1,68 @@ +using System; +using System.Collections.Generic; +using ICD.Common.Properties; + +namespace ICD.Common.Utils.Extensions +{ + /// + /// Extension methods for working with Lists. + /// + public static class ListExtensions + { + /// + /// Adds the item into a sorted list. + /// + /// + /// + /// + [PublicAPI] + public static void AddSorted(this List extends, T item) + { + if (extends == null) + throw new ArgumentNullException("extends"); + + extends.AddSorted(item, Comparer.Default); + } + + /// + /// Adds the item into a sorted list. + /// + /// + /// + /// + /// + [PublicAPI] + public static void AddSorted(this List extends, T item, IComparer comparer) + { + if (extends == null) + throw new ArgumentNullException("extends"); + + if (comparer == null) + throw new ArgumentNullException("comparer"); + + if (extends.Count == 0) + { + extends.Add(item); + return; + } + + if (comparer.Compare(extends[extends.Count - 1], item) <= 0) + { + extends.Add(item); + return; + } + + if (comparer.Compare(extends[0], item) >= 0) + { + extends.Insert(0, item); + return; + } + + int index = extends.BinarySearch(item); + if (index < 0) + index = ~index; + + extends.Insert(index, item); + } + } +} diff --git a/ICD.Common.Utils/ICD.Common.Utils_SimplSharp.csproj b/ICD.Common.Utils/ICD.Common.Utils_SimplSharp.csproj index c39b3ae..b6944e9 100644 --- a/ICD.Common.Utils/ICD.Common.Utils_SimplSharp.csproj +++ b/ICD.Common.Utils/ICD.Common.Utils_SimplSharp.csproj @@ -85,6 +85,7 @@ + From 323300f710401462bd7ac05587d4a064ed874a36 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Fri, 21 Jul 2017 11:01:32 -0400 Subject: [PATCH 6/6] Rethrowing XmlExceptions as IcdXmlExceptions --- ICD.Common.Utils/Xml/IcdXmlDocument.cs | 2 +- ICD.Common.Utils/Xml/IcdXmlException.cs | 14 ++++ ICD.Common.Utils/Xml/IcdXmlReader.cs | 105 ++++++++++++++++++++---- ICD.Common.Utils/Xml/XmlUtils.cs | 9 ++ 4 files changed, 115 insertions(+), 15 deletions(-) diff --git a/ICD.Common.Utils/Xml/IcdXmlDocument.cs b/ICD.Common.Utils/Xml/IcdXmlDocument.cs index cd2973b..09a50f1 100644 --- a/ICD.Common.Utils/Xml/IcdXmlDocument.cs +++ b/ICD.Common.Utils/Xml/IcdXmlDocument.cs @@ -28,7 +28,7 @@ namespace ICD.Common.Utils.Xml } catch (XmlException e) { - throw new IcdXmlException(e.Message, e, e.LineNumber, e.LinePosition); + throw new IcdXmlException(e); } } diff --git a/ICD.Common.Utils/Xml/IcdXmlException.cs b/ICD.Common.Utils/Xml/IcdXmlException.cs index 708228f..984fbb4 100644 --- a/ICD.Common.Utils/Xml/IcdXmlException.cs +++ b/ICD.Common.Utils/Xml/IcdXmlException.cs @@ -1,4 +1,9 @@ using System; +#if SIMPLSHARP +using Crestron.SimplSharp; +#else +using System.Xml; +#endif namespace ICD.Common.Utils.Xml { @@ -20,5 +25,14 @@ namespace ICD.Common.Utils.Xml m_LineNumber = lineNumber; m_LinePosition = linePosition; } + + /// + /// Constructor. + /// + /// + public IcdXmlException(XmlException inner) + : this(inner.Message, inner, inner.LineNumber, inner.LinePosition) + { + } } } diff --git a/ICD.Common.Utils/Xml/IcdXmlReader.cs b/ICD.Common.Utils/Xml/IcdXmlReader.cs index 4103949..109c9db 100644 --- a/ICD.Common.Utils/Xml/IcdXmlReader.cs +++ b/ICD.Common.Utils/Xml/IcdXmlReader.cs @@ -50,26 +50,54 @@ namespace ICD.Common.Utils.Xml public bool MoveToNextAttribute() { - return m_Reader.MoveToNextAttribute(); + try + { + return m_Reader.MoveToNextAttribute(); + } + catch (XmlException e) + { + throw new IcdXmlException(e); + } } public void MoveToElement() { - m_Reader.MoveToElement(); + try + { + m_Reader.MoveToElement(); + } + catch (XmlException e) + { + throw new IcdXmlException(e); + } } public string GetAttribute(string name) { - return m_Reader.GetAttribute(name); + try + { + return m_Reader.GetAttribute(name); + } + catch (XmlException e) + { + throw new IcdXmlException(e); + } } public string ReadString() { + try + { #if SIMPLSHARP - return m_Reader.ReadString(); + return m_Reader.ReadString(); #else - return m_Reader.ReadElementContentAsString(); + return m_Reader.ReadElementContentAsString(); #endif + } + catch (XmlException e) + { + throw new IcdXmlException(e); + } } public bool Read() @@ -80,47 +108,96 @@ namespace ICD.Common.Utils.Xml } catch (XmlException e) { - throw new IcdXmlException(e.Message, e, e.LineNumber, e.LinePosition); + throw new IcdXmlException(e); } } public void Dispose() { + try + { #if SIMPLSHARP - m_Reader.Dispose(true); + m_Reader.Dispose(true); #else - m_Reader.Dispose(); + m_Reader.Dispose(); #endif + } + catch (XmlException e) + { + throw new IcdXmlException(e); + } } public void Skip() { - m_Reader.Skip(); + try + { + m_Reader.Skip(); + } + catch (XmlException e) + { + throw new IcdXmlException(e); + } } public string ReadElementContentAsString() { - return m_Reader.ReadElementContentAsString(); + try + { + return m_Reader.ReadElementContentAsString(); + } + catch (XmlException e) + { + throw new IcdXmlException(e); + } } public string ReadOuterXml() { - return m_Reader.ReadOuterXml(); + try + { + return m_Reader.ReadOuterXml(); + } + catch (XmlException e) + { + throw new IcdXmlException(e); + } } public string ReadInnerXml() { - return m_Reader.ReadInnerXml(); + try + { + return m_Reader.ReadInnerXml(); + } + catch (XmlException e) + { + throw new IcdXmlException(e); + } } public long ReadElementContentAsLong() { - return m_Reader.ReadElementContentAsLong(); + try + { + return m_Reader.ReadElementContentAsLong(); + } + catch (XmlException e) + { + throw new IcdXmlException(e); + } } public float ReadElementContentAsFloat() { - return m_Reader.ReadElementContentAsFloat(); + try + { + return m_Reader.ReadElementContentAsFloat(); + } + catch (XmlException e) + { + throw new IcdXmlException(e); + } } #endregion diff --git a/ICD.Common.Utils/Xml/XmlUtils.cs b/ICD.Common.Utils/Xml/XmlUtils.cs index 4a224dd..ee07697 100644 --- a/ICD.Common.Utils/Xml/XmlUtils.cs +++ b/ICD.Common.Utils/Xml/XmlUtils.cs @@ -135,6 +135,9 @@ namespace ICD.Common.Utils.Xml [PublicAPI] public static void Recurse(string xml, Action callback) { + if (callback == null) + throw new ArgumentNullException("callback"); + Recurse(xml, new Stack(), callback); } @@ -146,6 +149,12 @@ namespace ICD.Common.Utils.Xml /// private static void Recurse(string xml, Stack path, Action callback) { + if (path == null) + throw new ArgumentNullException("path"); + + if (callback == null) + throw new ArgumentNullException("callback"); + IcdXmlReader childReader; try