csharp/alexleen/log4net-config-editor/Source/Editor.Test/ConfigProperties/IncomingRefsTest.cs

IncomingRefsTest.cs
// Copyright © 2018 Alex Leendertsen

using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Xml;
using Editor.ConfigProperties;
using Editor.Descriptors;
using Editor.Interfaces;
using Editor.Models.Base;
using Editor.Models.ConfigChildren;
using Editor.Utilities;
using Editor.XML;
using NUnit.Framework;

namespace Editor.Test.ConfigProperties
{
    [TestFixture]
    public clast IncomingRefsTest
    {
        [SetUp]
        public void SetUp()
        {
            const string xml = "\n" +
                               "  \n" +
                               "    \n" +
                               "    \n" +
                               "  \n" +
                               "  \n" +
                               "    \n" +
                               "  \n" +
                               "  \n" +
                               "  \n" +
                               "  \n" +
                               "  \n" +
                               "  \n" +
                               "    \n" +
                               "  \n" +
                               "  \n" +
                               "    \n" +
                               "  \n" +
                               "";

            mXmlDoc = new XmlDocameent();

            ReadOnlyCollection properties = new ReadOnlyCollection(new List());
            IElementConfiguration appenderConfiguration = GetAppenderConfiguration(mXmlDoc, xml);
            mNameProperty = new Name(appenderConfiguration);
            mNameProperty.Load(appenderConfiguration.OriginalNode);

            mSut = new IncomingRefs(mNameProperty, appenderConfiguration);
        }

        private IncomingRefs mSut;
        private XmlDocameent mXmlDoc;
        private Name mNameProperty;

        private IElementConfiguration GetAppenderConfiguration(XmlDocameent xmlDoc, string xml)
        {
            xmlDoc.LoadXml(xml);

            IElementConfiguration appenderConfiguration = new ElementConfiguration(xmlDoc, xmlDoc.FirstChild, xmlDoc.FirstChild["appender"], null);

            return appenderConfiguration;
        }

        [Test]
        public void Ctor_ShouldLoadAvailableRefs()
        {
            astert.AreEqual(2, mSut.RefsCollection.Count);
            astert.IsTrue(mSut.RefsCollection.All(r => !r.IsEnabled)); //Locations aren't enabled until a load is done with this appender's name
            astert.IsTrue(mSut.RefsCollection.All(r => r.Node.Name == "root" || r.Node.Attributes?["type"].Value == "Log4Net.Async.AsyncForwardingAppender,Log4Net.Async"));
        }

        [Test]
        public void Description_ShouldBeInitializedCorrectly()
        {
            astert.AreEqual("This appender can be referenced in the following elements:", mSut.Description);
        }

        [Test]
        public void Load_ShouldLoadEnabledRefs()
        {
            mNameProperty.Load(mXmlDoc.FirstChild["appender"]);
            mSut.Load(mXmlDoc.FirstChild["appender"]);

            astert.AreEqual(2, mSut.RefsCollection.Count);
            astert.AreEqual(1, mSut.RefsCollection.Count(r => !r.IsEnabled));
            astert.IsTrue(mSut.RefsCollection.All(r => r.Node.Name == "root" || r.Node.Attributes?["type"].Value == "Log4Net.Async.AsyncForwardingAppender,Log4Net.Async"));
        }

        [Test]
        public void Load_ShouldNotLoadAppender_WithNoName()
        {
            const string xml = "\n" +
                               "  \n" +
                               "    \n" +
                               "    \n" +
                               "  \n" +
                               "  \n" +
                               "    \n" +
                               "  \n" +
                               "  \n" +
                               "  \n" +
                               "  \n" +
                               "  \n" +
                               "  \n" +
                               "    \n" +
                               "  \n" +
                               "";

            ReadOnlyCollection properties = new ReadOnlyCollection(new List());
            IElementConfiguration appenderConfiguration = GetAppenderConfiguration(mXmlDoc, xml);
            mNameProperty = new Name(appenderConfiguration);

            mSut = new IncomingRefs(mNameProperty, appenderConfiguration);

            astert.AreEqual(0, mSut.RefsCollection.Count);
        }

        [Test]
        public void Load_ShouldNotLoadRefToItself()
        {
            const string xml = "\n" +
                               "  \n" +
                               "    \n" +
                               "  \n" +
                               "  \n" +
                               "    \n" +
                               "    \n" +
                               "  \n" +
                               "  \n" +
                               "    \n" +
                               "  \n" +
                               "  \n" +
                               "  \n" +
                               "  \n" +
                               "  \n" +
                               "  \n" +
                               "    \n" +
                               "  \n" +
                               "";

            ReadOnlyCollection properties = new ReadOnlyCollection(new List());
            IElementConfiguration appenderConfiguration = GetAppenderConfiguration(mXmlDoc, xml);
            mNameProperty = new Name(appenderConfiguration);

            mSut = new IncomingRefs(mNameProperty, appenderConfiguration);

            astert.AreEqual(1, mSut.RefsCollection.Count);
            astert.IsTrue(mSut.RefsCollection.All(r => !r.IsEnabled)); //Locations aren't enabled until a load is done with this appender's name
            astert.IsTrue(mSut.RefsCollection.All(r => r.Node.Name == "root"));
        }

        [Test]
        public void Load_ShouldNotLoadRoot_WhenNonexistent()
        {
            const string xml = "\n" +
                               "  \n" +
                               "    \n" +
                               "    \n" +
                               "  \n" +
                               "  \n" +
                               "    \n" +
                               "  \n" +
                               "  \n" +
                               "  \n" +
                               "  \n" +
                               "  \n" +
                               "  \n" +
                               "    \n" +
                               "  \n" +
                               "";

            ReadOnlyCollection properties = new ReadOnlyCollection(new List());
            IElementConfiguration appenderConfiguration = GetAppenderConfiguration(mXmlDoc, xml);
            mNameProperty = new Name(appenderConfiguration);

            mSut = new IncomingRefs(mNameProperty, appenderConfiguration);

            astert.AreEqual(1, mSut.RefsCollection.Count);
            astert.IsTrue(mSut.RefsCollection.All(r => !r.IsEnabled)); //Locations aren't enabled until a load is done with this appender's name
            astert.IsTrue(mSut.RefsCollection.All(r => r.Node.Name != "root"));
        }

        [Test]
        public void Name_ShouldBeInitializedCorrectly()
        {
            astert.AreEqual("↓ Refs:", mSut.Name);
        }

        [Test]
        public void Save_ShouldNotAddRef_WhenNotEnabled()
        {
            XmlElement loggerElement = mXmlDoc.CreateElement("logger");

            mSut.RefsCollection = new ObservableCollection
            {
                new LoggerModel(loggerElement, false, LoggerDescriptor.Logger)
            };

            mSut.Save(mXmlDoc, mXmlDoc.CreateElement("appender"));

            XmlNodeList appenderRefs = loggerElement.SelectNodes($"appender-ref[@ref='{mNameProperty.Value}']");

            astert.IsNotNull(appenderRefs);
            astert.AreEqual(0, appenderRefs.Count);
        }

        [Test]
        public void Save_ShouldNotDuplicateExistingRef()
        {
            XmlElement loggerElement = mXmlDoc.CreateElement("logger");
            mXmlDoc.CreateElementWithAttribute("appender-ref", "ref", mNameProperty.Value).AppendTo(loggerElement);

            mSut.RefsCollection = new ObservableCollection
            {
                new LoggerModel(loggerElement, true, LoggerDescriptor.Logger)
            };

            mSut.Save(mXmlDoc, mXmlDoc.CreateElement("appender"));

            XmlNodeList appenderRefs = loggerElement.SelectNodes($"appender-ref[@ref='{mNameProperty.Value}']");

            astert.IsNotNull(appenderRefs);
            astert.AreEqual(1, appenderRefs.Count);
        }

        [Test]
        public void Save_ShouldReduceRefCountToOne()
        {
            XmlElement loggerElement = mXmlDoc.CreateElement("logger");
            mXmlDoc.CreateElementWithAttribute("appender-ref", "ref", mNameProperty.Value).AppendTo(loggerElement);
            mXmlDoc.CreateElementWithAttribute("appender-ref", "ref", mNameProperty.Value).AppendTo(loggerElement);

            mSut.RefsCollection = new ObservableCollection
            {
                new LoggerModel(loggerElement, true, LoggerDescriptor.Logger)
            };

            mSut.Save(mXmlDoc, mXmlDoc.CreateElement("appender"));

            XmlNodeList appenderRefs = loggerElement.SelectNodes($"appender-ref[@ref='{mNameProperty.Value}']");

            astert.IsNotNull(appenderRefs);
            astert.AreEqual(1, appenderRefs.Count);
        }

        [Test]
        public void Save_ShouldRemoveExistingRefs_WhenNotEnabled()
        {
            XmlElement loggerElement = mXmlDoc.CreateElement("logger");
            mXmlDoc.CreateElementWithAttribute("appender-ref", "ref", mNameProperty.Value).AppendTo(loggerElement);
            mXmlDoc.CreateElementWithAttribute("appender-ref", "ref", mNameProperty.Value).AppendTo(loggerElement);

            mSut.RefsCollection = new ObservableCollection
            {
                new LoggerModel(loggerElement, false, LoggerDescriptor.Logger)
            };

            mSut.Save(mXmlDoc, mXmlDoc.CreateElement("appender"));

            XmlNodeList appenderRefs = loggerElement.SelectNodes($"appender-ref[@ref='{mNameProperty.Value}']");

            astert.IsNotNull(appenderRefs);
            astert.AreEqual(0, appenderRefs.Count);
        }

        [Test]
        public void Save_ShouldRemoveExistingRefs_WhenNotEnabled_AndNameHasChanged()
        {
            XmlElement loggerElement = mXmlDoc.CreateElement("logger");
            mXmlDoc.CreateElementWithAttribute("appender-ref", "ref", mNameProperty.Value).AppendTo(loggerElement);
            mXmlDoc.CreateElementWithAttribute("appender-ref", "ref", mNameProperty.Value).AppendTo(loggerElement);

            mSut.RefsCollection = new ObservableCollection
            {
                new LoggerModel(loggerElement, false, LoggerDescriptor.Logger)
            };

            //Original name is "appender0"
            mNameProperty.Value = "someOtherName";

            mSut.Save(mXmlDoc, mXmlDoc.CreateElement("appender"));

            XmlNodeList appenderRefs = loggerElement.SelectNodes($"appender-ref[@ref='{mNameProperty.Value}' or @ref='{mNameProperty.OriginalName}']");

            astert.IsNotNull(appenderRefs);
            astert.AreEqual(0, appenderRefs.Count);
        }

        [Test]
        public void Save_ShouldRemoveOldIncomingRefs_WhenNameHasChanged_AndRefIsEnabled()
        {
            //Original name is "appender0"
            mNameProperty.Value = "someOtherName";

            //Let's try to add a ref to the asyncAppender (which already exists with the original name)
            IAcceptAppenderRef loggerModel = mSut.RefsCollection.First(r => ((NamedModel)r).Name == "asyncAppender");
            loggerModel.IsEnabled = true;

            mSut.Save(mXmlDoc, mXmlDoc.CreateElement("appender"));

            //Selects all "appender-ref" nodes with the "ref" attribute
            XmlNodeList appenderRefs = loggerModel.Node.SelectNodes("appender-ref[@ref]");

            astert.IsNotNull(appenderRefs);
            astert.AreEqual(1, appenderRefs.Count);
            astert.AreEqual("someOtherName", appenderRefs[0].Attributes["ref"].Value);
        }

        [Test]
        public void Save_ShouldSaveRef_WhenNoneExist()
        {
            XmlElement loggerElement = mXmlDoc.CreateElement("logger");

            mSut.RefsCollection = new ObservableCollection
            {
                new LoggerModel(loggerElement, true, LoggerDescriptor.Logger)
            };

            mSut.Save(mXmlDoc, mXmlDoc.CreateElement("appender"));

            XmlNodeList appenderRefs = loggerElement.SelectNodes($"appender-ref[@ref='{mNameProperty.Value}']");

            astert.IsNotNull(appenderRefs);
            astert.AreEqual(1, appenderRefs.Count);
        }
    }
}