using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; using System.Xml; using System.Xml.Linq; using System.Xml.XPath; using NUnit.Framework; using Umbraco.Core; using Umbraco.Tests.TestHelpers; using umbraco; namespace Umbraco.Tests { [TestFixture] public class XmlHelperTests { [SetUp] public void Setup() { TestHelper.SetupLog4NetForTests(); } [Ignore("This is a benchmark test so is ignored by default")] [Test] public void Sort_Nodes_Benchmark_Legacy() { var xmlContent = GetXmlContent(1); var xml = new XmlDocument(); xml.LoadXml(xmlContent); var original = xml.GetElementById(1173.ToString()); Assert.IsNotNull(original); long totalTime = 0; var watch = new Stopwatch(); var iterations = 10000; for (var i = 0; i < iterations; i++) { //don't measure the time for clone! var parentNode = original.Clone(); watch.Start(); LegacySortNodes(ref parentNode); watch.Stop(); totalTime += watch.ElapsedMilliseconds; watch.Reset(); //do assertions just to make sure it is working properly. var currSort = 0; foreach (var child in parentNode.SelectNodes("./* [@id]").Cast()) { Assert.AreEqual(currSort, int.Parse(child.Attributes["sortOrder"].Value)); currSort++; } //ensure the parent node's properties still exist first Assert.AreEqual("content", parentNode.ChildNodes[0].Name); Assert.AreEqual("umbracoUrlAlias", parentNode.ChildNodes[1].Name); //then the child nodes should come straight after Assert.IsTrue(parentNode.ChildNodes[2].Attributes["id"] != null); } Debug.WriteLine("Total time for " + iterations + " iterations is " + totalTime); } [Ignore("This is a benchmark test so is ignored by default")] [Test] public void Sort_Nodes_Benchmark_New() { var xmlContent = GetXmlContent(1); var xml = new XmlDocument(); xml.LoadXml(xmlContent); var original = xml.GetElementById(1173.ToString()); Assert.IsNotNull(original); long totalTime = 0; var watch = new Stopwatch(); var iterations = 10000; for (var i = 0; i < iterations; i++) { //don't measure the time for clone! var parentNode = (XmlElement)original.Clone(); watch.Start(); XmlHelper.SortNodes( parentNode, "./* [@id]", element => element.Attribute("id") != null, element => element.AttributeValue("sortOrder")); watch.Stop(); totalTime += watch.ElapsedMilliseconds; watch.Reset(); //do assertions just to make sure it is working properly. var currSort = 0; foreach (var child in parentNode.SelectNodes("./* [@id]").Cast()) { Assert.AreEqual(currSort, int.Parse(child.Attributes["sortOrder"].Value)); currSort++; } //ensure the parent node's properties still exist first Assert.AreEqual("content", parentNode.ChildNodes[0].Name); Assert.AreEqual("umbracoUrlAlias", parentNode.ChildNodes[1].Name); //then the child nodes should come straight after Assert.IsTrue(parentNode.ChildNodes[2].Attributes["id"] != null); } Debug.WriteLine("Total time for " + iterations + " iterations is " + totalTime); } [Test] public void Sort_Nodes() { var xmlContent = GetXmlContent(1); var xml = new XmlDocument(); xml.LoadXml(xmlContent); var original = xml.GetElementById(1173.ToString()); Assert.IsNotNull(original); var parentNode = (XmlElement)original.Clone(); XmlHelper.SortNodes( parentNode, "./* [@id]", element => element.Attribute("id") != null, element => element.AttributeValue("sortOrder")); //do assertions just to make sure it is working properly. var currSort = 0; foreach (var child in parentNode.SelectNodes("./* [@id]").Cast()) { Assert.AreEqual(currSort, int.Parse(child.Attributes["sortOrder"].Value)); currSort++; } //ensure the parent node's properties still exist first Assert.AreEqual("content", parentNode.ChildNodes[0].Name); Assert.AreEqual("umbracoUrlAlias", parentNode.ChildNodes[1].Name); //then the child nodes should come straight after Assert.IsTrue(parentNode.ChildNodes[2].Attributes["id"] != null); } /// /// This was the logic to sort before and now lives here just to show the benchmarks tests above. /// /// private static void LegacySortNodes(ref XmlNode parentNode) { XmlNode n = parentNode.CloneNode(true); // remove all children from original node string xpath = UmbracoSettings.UseLegacyXmlSchema ? "./node" : "./* [@id]"; foreach (XmlNode child in parentNode.SelectNodes(xpath)) parentNode.RemoveChild(child); XPathNavigator nav = n.CreateNavigator(); XPathExpression expr = nav.Compile(xpath); expr.AddSort("@sortOrder", XmlSortOrder.Ascending, XmlCaseOrder.None, "", XmlDataType.Number); XPathNodeIterator iterator = nav.Select(expr); while (iterator.MoveNext()) parentNode.AppendChild( ((IHasXmlNode)iterator.Current).GetNode()); } /// /// returns xml with a reverse sort order /// /// /// private string GetXmlContent(int templateId) { return @" ]> 1 This is some content]]> "; } } }