using NUnit.Framework; using System; using Mono.Documentation; using System.Xml; using System.Xml.XPath; using System.Linq; using Mono.Cecil; using System.Collections.Generic; using Mono.Documentation.Updater.Frameworks; using Mono.Documentation.Updater; using System.Runtime.InteropServices; using Mono.Documentation.Updater.Formatters; namespace mdoc.Test { public class OneAttribute : Attribute { } public class TwoAttribute : Attribute { } [One] public class MyClass { [One] public void Meth (int a, string d, int c) { } } public class MyClass2 { public void Meth (int a, string b, int c) { } } public class MyComplicatedClass { public IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback cback, object state) => null; } } namespace mdoc.Test2 { using mdoc.Test; [One, Two] public class MyClass { [One, Two] public void Meth (int a, string b, int c) { } } [Two] public class MyClass2 { [Two] public void Meth (int d, string e, int f) { } } } namespace mdoc.Test3 { public class MyClass { public void Meth(int a, string b, int c) { } } public class MyClass2 { public void Meth(int A, string B, int C) { } } } namespace mdoc.Test { /// /// Tests functions that update the EcmaXMl under various conditions from /// corresponding classes. /// [TestFixture ()] public class XmlUpdateTests { class ParamContext { public XmlDocument doc; public string beforeXML; public MethodReference method; public List parameters; public MDocUpdater updater; public FrameworkIndex fx; } #region Myclass Tests [Test ()] public void Parameters_Updating_Normal () { var context = InitContext (startingEmptyXml, 0); FrameworkTypeEntry typeEntry = context.fx.Frameworks[0].Types.First (); context.fx.Frameworks.RemoveAt(2); context.fx.Frameworks.RemoveAt(1); bool fxAlternateTriggered = false; context.updater.MakeParameters (context.doc.FirstChild as XmlElement, context.method, context.parameters, typeEntry, ref fxAlternateTriggered); var afterXML = context.doc.OuterXml; Assert.AreEqual (Normalize(normalSingleXml), afterXML); } [Test ()] public void Parameters_Updating_Existing_MultiFramework () { var context = InitContext (multiFrameworkXml, 0); FrameworkTypeEntry typeEntry = context.fx.Frameworks[0].Types.First (); bool fxAlternateTriggered = false; context.updater.MakeParameters (context.doc.FirstChild as XmlElement, context.method, context.parameters, typeEntry, ref fxAlternateTriggered); var afterXML = context.doc.OuterXml; // the original state was cleared out on account that this was the first of the frameworks Assert.AreEqual (Normalize(XmlConsts.NormalSingleXml), Normalize(afterXML)); } #endregion #region MyClass2 tests [Test ()] public void Parameters2_Updating_Normal () { var context = InitContext (startingEmptyXml, 0); FrameworkTypeEntry typeEntry = context.fx.Frameworks[0].Types.First (); bool fxAlternateTriggered = false; context.updater.MakeParameters (context.doc.FirstChild as XmlElement, context.method, context.parameters, typeEntry, ref fxAlternateTriggered); var afterXML = context.doc.OuterXml; Assert.AreEqual (Normalize (XmlConsts.NormalSingleXml2), afterXML); } [Test ()] public void Parameters_Updating_Normal22 () { var context = InitContext (XmlConsts.NormalSingleXml2, 1); FrameworkTypeEntry typeEntry = context.fx.Frameworks[1].Types.First (); bool fxAlternateTriggered = false; context.updater.MakeParameters (context.doc.FirstChild as XmlElement, context.method, context.parameters, typeEntry, ref fxAlternateTriggered); var afterXML = context.doc.OuterXml; Assert.AreEqual (Normalize (XmlConsts.MultiFrameworkXml2Second), afterXML); } [Test ()] public void Parameters_Updating_Normal32 () { var context = InitContext (XmlConsts.MultiFrameworkXml2Second, 2); FrameworkTypeEntry typeEntry = context.fx.Frameworks[2].Types.First (); bool fxAlternateTriggered = false; context.updater.MakeParameters (context.doc.FirstChild as XmlElement, context.method, context.parameters, typeEntry, ref fxAlternateTriggered); var afterXML = context.doc.OuterXml; Assert.AreEqual (Normalize (XmlConsts.MultiFrameworkXml2), afterXML); } [Test()] public void Parameters_Updating_BeginRead() { FrameworkIndex fx = new FrameworkIndex("", 3, null); fx.Frameworks.Add(new FrameworkEntry(fx.Frameworks, fx.Frameworks) { Id = "One", Name = "One", Replace = "mdoc.Test2", With = "mdoc.Test" }); fx.Frameworks.Add(new FrameworkEntry(fx.Frameworks, fx.Frameworks) { Id = "Two", Name = "Two", Replace = "mdoc.Test2", With = "mdoc.Test" }); fx.Frameworks.Add(new FrameworkEntry(fx.Frameworks, fx.Frameworks) { Id = "Three", Name = "Three", Replace = "mdoc.Test2", With = "mdoc.Test" }); var context = InitComplexContext(XmlConsts.XML_METHOD_TESTMETHOD_BEFORE, "mdoc.Test", "BeginRead", fx); var theType = context.method.DeclaringType.Resolve(); foreach (var it in fx.Frameworks) { var t = it.ProcessType(theType, theType.Module.Assembly); foreach(var m in theType.Methods) { t.ProcessMember(m); } } var typeEntry = context.fx.Frameworks[2].Types.First(); bool fxAlternateTriggered = true; context.updater.MakeParameters(context.doc.FirstChild as XmlElement, context.method, context.parameters, typeEntry, ref fxAlternateTriggered); var afterXML = context.doc.OuterXml; // TODO: make representative post-method XML Assert.AreEqual(Normalize(XmlConsts.XML_METHOD_TESTMETHOD_AFTER), afterXML); } [Test ()] public void Parameters_Updating_Existing_MultiFramework22 () { var context = InitContext (XmlConsts.MultiFrameworkXml2, 0); FrameworkTypeEntry typeEntry = context.fx.Frameworks[0].Types.First (); bool fxAlternateTriggered = false; context.updater.MakeParameters (context.doc.FirstChild as XmlElement, context.method, context.parameters, typeEntry, ref fxAlternateTriggered); var afterXML = context.doc.OuterXml; Assert.AreEqual (Normalize(XmlConsts.NormalSingleXml2), Normalize (afterXML)); } [Test ()] public void Parameters_Updating_Existing_MultiFramework222 () { var context = InitContext (XmlConsts.MultiFrameworkXml2, 2); FrameworkTypeEntry typeEntry = context.fx.Frameworks[2].Types.First (); bool fxAlternateTriggered = false; context.updater.MakeParameters (context.doc.FirstChild as XmlElement, context.method, context.parameters, typeEntry, ref fxAlternateTriggered); var afterXML = context.doc.OuterXml; Assert.AreEqual (context.beforeXML, Normalize (afterXML)); } [Test ()] public void Parameters_Updating_Existing_Align2 () { var context = InitContext (XmlConsts.MultiFrameworkXml2, 1, forceAlignment: true); FrameworkTypeEntry typeEntry = context.fx.Frameworks[1].Types.First (); bool fxAlternateTriggered = false; context.updater.MakeParameters (context.doc.FirstChild as XmlElement, context.method, context.parameters, typeEntry, ref fxAlternateTriggered); var afterXML = context.doc.OuterXml; Assert.IsFalse (fxAlternateTriggered); Assert.AreEqual (Normalize (XmlConsts.MultiFrameworkAligned2), Normalize (afterXML)); } #endregion #region Simple Parameter Change across multi FX [Test ()] public void Parameters_Updating_Existing_NameChange () { var context = InitContext (XmlConsts.NormalSingleXml2, 1, forceAlignment: false); Func typeEntry = i => context.fx.Frameworks[i].Types.First (); bool fxAlternateTriggered = false; context.updater.MakeParameters (context.doc.FirstChild as XmlElement, context.method, context.parameters, typeEntry(0), ref fxAlternateTriggered); // this will be false, since it clears out the parameters list on the first run Assert.IsFalse (fxAlternateTriggered, "first run"); fxAlternateTriggered = false; context.updater.MakeParameters (context.doc.FirstChild as XmlElement, context.method, context.parameters, typeEntry (1), ref fxAlternateTriggered); Assert.IsFalse (fxAlternateTriggered, "second run"); fxAlternateTriggered = false; context.updater.MakeParameters (context.doc.FirstChild as XmlElement, context.method, context.parameters, typeEntry (2), ref fxAlternateTriggered); Assert.IsFalse (fxAlternateTriggered, "third run"); var afterXML = context.doc.OuterXml; Assert.AreEqual (Normalize (XmlConsts.MultiFrameworkAlignedOther), Normalize (afterXML)); } #endregion #region Parameter Name Alpha Diff [Test()] public void Parameters3_Making_NameDiff() { var context = InitContext(startingEmptyXml, 0, false, ns1: "mdoc.Test3", ns2: "mdoc.Test3"); var context2 = InitContext(startingEmptyXml, 1, false, ns1: "mdoc.Test3", ns2: "mdoc.Test3"); FrameworkTypeEntry typeEntry = context.fx.Frameworks[0].Types.First(); FrameworkTypeEntry typeEntry2 = context.fx.Frameworks[1].Types.First(); bool fxAlternateTriggered = false; context.updater.MakeParameters(context.doc.FirstChild as XmlElement, context.method, context.parameters, typeEntry, ref fxAlternateTriggered); context.updater.MakeParameters(context.doc.FirstChild as XmlElement, context2.method, context2.parameters, typeEntry2, ref fxAlternateTriggered); var afterXML = context.doc.OuterXml; Assert.IsTrue(afterXML.Contains("Parameter Name=\"a\""), "missing 'a'"); Assert.IsTrue(afterXML.Contains("Parameter Name=\"b\""), "missing 'b'"); Assert.IsTrue(afterXML.Contains("Parameter Name=\"c\""), "missing 'c'"); Assert.IsTrue(afterXML.Contains("Parameter Name=\"A\""), "missing 'A'"); Assert.IsTrue(afterXML.Contains("Parameter Name=\"B\""), "missing 'B'"); Assert.IsTrue(afterXML.Contains("Parameter Name=\"C\""), "missing 'C'"); } [Test()] public void Parameters3_Updating_NameDiff() { var context = InitContext(startingEmptyXml, 0, false, ns1: "mdoc.Test3", ns2: "mdoc.Test3"); var context2 = InitContext(startingEmptyXml, 1, false, ns1: "mdoc.Test3", ns2: "mdoc.Test3"); var context3 = InitContext(startingEmptyXml, 2, false, ns1: "mdoc.Test3", ns2: "mdoc.Test3"); FrameworkTypeEntry typeEntry = context.fx.Frameworks[0].Types.First(); FrameworkTypeEntry typeEntry2 = context.fx.Frameworks[1].Types.First(); FrameworkTypeEntry typeEntry3 = context.fx.Frameworks[2].Types.First(); bool fxAlternateTriggered = false; context.updater.MakeParameters(context.doc.FirstChild as XmlElement, context.method, context.parameters, typeEntry, ref fxAlternateTriggered); context.updater.UpdateParameters(context.doc.FirstChild as XmlElement, "param", context.parameters.Select(p => p.Name).ToArray(), typeEntry); context.updater.MakeParameters(context.doc.FirstChild as XmlElement, context2.method, context2.parameters, typeEntry2, ref fxAlternateTriggered); context.updater.UpdateParameters(context.doc.FirstChild as XmlElement, "param", context2.parameters.Select(p => p.Name).ToArray(), typeEntry2); context.updater.MakeParameters(context.doc.FirstChild as XmlElement, context3.method, context3.parameters, typeEntry3, ref fxAlternateTriggered); context.updater.UpdateParameters(context.doc.FirstChild as XmlElement, "param", context3.parameters.Select(p => p.Name).ToArray(), typeEntry3); var afterXML = context.doc.OuterXml; Assert.IsTrue(afterXML.Contains("param name=\"a\""), "missing 'a'"); Assert.IsTrue(afterXML.Contains("param name=\"b\""), "missing 'b'"); Assert.IsTrue(afterXML.Contains("param name=\"c\""), "missing 'c'"); Assert.IsTrue(afterXML.Contains("param name=\"A\""), "missing 'A'"); Assert.IsTrue(afterXML.Contains("param name=\"B\""), "missing 'B'"); Assert.IsTrue(afterXML.Contains("param name=\"C\""), "missing 'C'"); } #endregion [Test ()] public void DocMemberEnumerator() { var context = InitContext (string.Format (typeFrameXml, multiFrameworkXml), 1, forceAlignment: true); FrameworkTypeEntry typeEntry = context.fx.Frameworks[1].Types.First (); var enumerator = new DocumentationEnumerator (); var matches = enumerator.GetDocumentationMembers (context.doc, context.method.DeclaringType.Resolve (), typeEntry); Assert.IsTrue (matches.Any (m => m.Member == context.method && m.Node != null), "didn't match the member"); } [Test ()] public void DocMemberEnumerator2 () { var context = InitContext (string.Format (typeFrameXml, multiFrameworkXml), 2, forceAlignment: true); FrameworkTypeEntry typeEntry = context.fx.Frameworks[2].Types.First (); var enumerator = new DocumentationEnumerator (); var matches = enumerator.GetDocumentationMembers (context.doc, context.method.DeclaringType.Resolve (), typeEntry); Assert.IsTrue (matches.Any (m => m.Member == context.method && m.Node != null), "didn't match the member"); } [Test] public void Attributes_TypeOrMethod() { var context = InitContext(string.Format(typeFrameXml, multiFrameworkXml), 2, forceAlignment: false); var fx = context.fx.Frameworks[1]; FrameworkTypeEntry typeEntry = fx.Types.First(); var attributeList = new[] { ((CustomAttribute)null, "One") }; MDocUpdater.MakeAttributes(context.doc.FirstChild as XmlElement, attributeList, typeEntry); var attrNode = context.doc.FirstChild.SelectSingleNode("Attributes"); var attributes = attrNode.SelectNodes("Attribute").Cast().ToArray(); Assert.IsTrue(attributes.Count() == 1); Assert.AreEqual("[One]", attributes[0].FirstChild.InnerText); Assert.AreEqual("Three", attributes[0].GetAttribute(Consts.FrameworkAlternate)); } [Test] public void Attributes_TypeOrMethod_AllFX () { var context = InitContext (string.Format (typeFrameXml, multiFrameworkXml), 2, forceAlignment: false); foreach (var fx in context.fx.Frameworks) { //var fx = context.fx.Frameworks[1]; FrameworkTypeEntry typeEntry = fx.Types.First (); var attributeList = new[] { ((CustomAttribute)null, "One") }; MDocUpdater.MakeAttributes (context.doc.FirstChild as XmlElement, attributeList, typeEntry); } var attrNode = context.doc.FirstChild.SelectSingleNode ("Attributes"); var attributes = attrNode.SelectNodes ("Attribute").Cast ().ToArray (); Assert.IsTrue (attributes.Count () == 1); Assert.AreEqual ("[One]", attributes[0].FirstChild.InnerText); Assert.IsFalse (attributes[0].HasAttribute (Consts.FrameworkAlternate)); } [Test] public void Attributes_TypeOrMethod_AllFX_OneMissing () { var context = InitContext (string.Format (typeFrameXml, multiFrameworkXml), 2, forceAlignment: false); foreach (var fx in context.fx.Frameworks) { //var fx = context.fx.Frameworks[1]; FrameworkTypeEntry typeEntry = fx.Types.First (); var attributeList = new[] { ((CustomAttribute)null, "One") }; if (fx.IsFirstFramework) attributeList = null; MDocUpdater.MakeAttributes (context.doc.FirstChild as XmlElement, attributeList, typeEntry); } var attrNode = context.doc.FirstChild.SelectSingleNode ("Attributes"); var attributes = attrNode.SelectNodes ("Attribute").Cast ().ToArray (); Assert.IsTrue (attributes.Count () == 1); Assert.AreEqual ("[One]", attributes[0].FirstChild.InnerText); Assert.IsTrue (attributes[0].HasAttribute (Consts.FrameworkAlternate)); Assert.AreEqual ("Three;Two", attributes[0].GetAttribute (Consts.FrameworkAlternate)); } [Test] public void Attributes_TypeOrMethod_AllFX_OneMissing_Last () { var context = InitContext (string.Format (typeFrameXml, multiFrameworkXml), 2, forceAlignment: false); foreach (var fx in context.fx.Frameworks) { //var fx = context.fx.Frameworks[1]; FrameworkTypeEntry typeEntry = fx.Types.First (); var attributeList = new[] { ((CustomAttribute)null, "One") }; if (fx.IsLastFramework) attributeList = null; MDocUpdater.MakeAttributes (context.doc.FirstChild as XmlElement, attributeList, typeEntry); } var attrNode = context.doc.FirstChild.SelectSingleNode ("Attributes"); var attributes = attrNode.SelectNodes ("Attribute").Cast ().ToArray (); Assert.IsTrue (attributes.Count () == 1); Assert.AreEqual ("[One]", attributes[0].FirstChild.InnerText); Assert.IsTrue (attributes[0].HasAttribute (Consts.FrameworkAlternate)); Assert.AreEqual ("One;Three", attributes[0].GetAttribute (Consts.FrameworkAlternate)); } [Test] public void Attributes_TypeOrMethod_AllFX_RunExisting_Middle () { var context = InitContext (string.Format (typeFrameXml, multiFrameworkXml), 2, forceAlignment: false); // first, go through and add "One" and "Two" to all of them foreach (var fx in context.fx.Frameworks) { FrameworkTypeEntry typeEntry = fx.Types.First (); var attributeList = new[] { ((CustomAttribute)null, "One"), ((CustomAttribute)null, "Two") }; MDocUpdater.MakeAttributes (context.doc.FirstChild as XmlElement, attributeList, typeEntry); } // Now, to test the first deployment on an existing set // in this case, the truth of the matter is that `Two` only exists in the middle foreach (var fx in context.fx.Frameworks) { FrameworkTypeEntry typeEntry = fx.Types.First (); var attributeList = new[] { ((CustomAttribute)null, "One") }; if (!fx.IsFirstFramework && !fx.IsLastFramework) { attributeList = new[] { ((CustomAttribute)null, "One"), ((CustomAttribute)null, "Two") }; } MDocUpdater.MakeAttributes (context.doc.FirstChild as XmlElement, attributeList, typeEntry); } var attrNode = context.doc.FirstChild.SelectSingleNode ("Attributes"); var attributes = attrNode.SelectNodes ("Attribute").Cast ().ToArray (); Assert.IsTrue (attributes.Count () == 2); Assert.AreEqual ("[One]", attributes[0].FirstChild.InnerText); Assert.IsFalse (attributes[0].HasAttribute (Consts.FrameworkAlternate)); Assert.AreEqual ("[Two]", attributes[1].FirstChild.InnerText); Assert.IsTrue (attributes[1].HasAttribute (Consts.FrameworkAlternate)); Assert.AreEqual ("Three", attributes[1].GetAttribute (Consts.FrameworkAlternate)); } [Test] public void Attributes_TypeOrMethod_AllFX_RunExisting_First () { var context = InitContext (string.Format (typeFrameXml, multiFrameworkXml), 2, forceAlignment: false); // first, go through and add "One" and "Two" to all of them foreach (var fx in context.fx.Frameworks) { FrameworkTypeEntry typeEntry = fx.Types.First (); var attributeList = new[] { ((CustomAttribute)null, "One"), ((CustomAttribute)null, "Two") }; MDocUpdater.MakeAttributes (context.doc.FirstChild as XmlElement, attributeList, typeEntry); } // Now, to test the first deployment on an existing set // in this case, the truth of the matter is that `Two` only exists in the middle foreach (var fx in context.fx.Frameworks) { FrameworkTypeEntry typeEntry = fx.Types.First (); var attributeList = new[] { ((CustomAttribute)null, "One") }; if (fx.IsFirstFramework) { attributeList = new[] { ((CustomAttribute)null, "One"), ((CustomAttribute)null, "Two") }; } MDocUpdater.MakeAttributes (context.doc.FirstChild as XmlElement, attributeList, typeEntry); } var attrNode = context.doc.FirstChild.SelectSingleNode ("Attributes"); var attributes = attrNode.SelectNodes ("Attribute").Cast ().ToArray (); Assert.IsTrue (attributes.Count () == 2); Assert.AreEqual ("[One]", attributes[0].FirstChild.InnerText); Assert.IsFalse (attributes[0].HasAttribute (Consts.FrameworkAlternate)); Assert.AreEqual ("[Two]", attributes[1].FirstChild.InnerText); Assert.IsTrue (attributes[1].HasAttribute (Consts.FrameworkAlternate)); Assert.AreEqual ("One", attributes[1].GetAttribute (Consts.FrameworkAlternate)); } [Test] public void Attributes_TypeOrMethod_AllFX_RunExisting_Last () { var context = InitContext (string.Format (typeFrameXml, multiFrameworkXml), 2, forceAlignment: false); // first, go through and add "One" and "Two" to all of them foreach (var fx in context.fx.Frameworks) { FrameworkTypeEntry typeEntry = fx.Types.First (); var attributeList = new[] { ((CustomAttribute)null, "One"), ((CustomAttribute)null, "Two") }; MDocUpdater.MakeAttributes (context.doc.FirstChild as XmlElement, attributeList, typeEntry); } foreach (var fx in context.fx.Frameworks) { FrameworkTypeEntry typeEntry = fx.Types.First (); var attributeList = new[] { ((CustomAttribute)null, "Two") }; if (fx.IsLastFramework) { attributeList = new[] { ((CustomAttribute)null, "One"), ((CustomAttribute)null, "Two") }; } MDocUpdater.MakeAttributes (context.doc.FirstChild as XmlElement, attributeList, typeEntry); } var attrNode = context.doc.FirstChild.SelectSingleNode ("Attributes"); var attributes = attrNode.SelectNodes ("Attribute").Cast ().ToArray (); Assert.IsTrue (attributes.Count () == 2); Assert.AreEqual ("[One]", attributes[1].FirstChild.InnerText); Assert.IsTrue (attributes[1].HasAttribute (Consts.FrameworkAlternate)); Assert.AreEqual ("Two", attributes[1].GetAttribute (Consts.FrameworkAlternate)); Assert.AreEqual ("[Two]", attributes[0].FirstChild.InnerText); Assert.IsFalse (attributes[0].HasAttribute (Consts.FrameworkAlternate)); } [Test] public void Attributes_TypeOrMethod_AllFX_OneMissing_Middle () { var context = InitContext (string.Format (typeFrameXml, multiFrameworkXml), 2, forceAlignment: false); foreach (var fx in context.fx.Frameworks) { //var fx = context.fx.Frameworks[1]; FrameworkTypeEntry typeEntry = fx.Types.First (); var attributeList = new[] { ((CustomAttribute)null, "One") }; if (!fx.IsLastFramework && !fx.IsFirstFramework) attributeList = null; MDocUpdater.MakeAttributes (context.doc.FirstChild as XmlElement, attributeList, typeEntry); } var attrNode = context.doc.FirstChild.SelectSingleNode ("Attributes"); var attributes = attrNode.SelectNodes ("Attribute").Cast ().ToArray (); Assert.IsTrue (attributes.Count () == 1); Assert.AreEqual ("[One]", attributes[0].FirstChild.InnerText); Assert.IsTrue (attributes[0].HasAttribute (Consts.FrameworkAlternate)); Assert.AreEqual ("One;Two", attributes[0].GetAttribute (Consts.FrameworkAlternate)); } [Test] [Ignore("Unable to mock valid AssemblySet, ignore for now")] public void Attributes_Assembly () { var context = InitContext (string.Format (typeFrameXml, multiFrameworkXml), 2, forceAlignment: false); foreach (var fx in context.fx.Frameworks) { FrameworkTypeEntry typeEntry = fx.Types.First (); var attributeList = new[] { ((CustomAttribute)null, "One") }; if (!fx.IsLastFramework && !fx.IsFirstFramework) { attributeList = null; } MDocUpdater.MakeAttributes( context.doc.FirstChild as XmlElement, attributeList, fx.IsFirstFrameworkForAssembly("one.dll"), fx.IsLastFrameworkForAssembly("one.dll"), () => fx.AllFrameworksStringWithAssembly("one.dll"), null, perLanguage: false); } var attrNode = context.doc.FirstChild.SelectSingleNode ("Attributes"); var attributes = attrNode.SelectNodes ("Attribute").Cast ().ToArray (); Assert.IsTrue (attributes.Count () == 1); Assert.AreEqual ("One", attributes[0].FirstChild.InnerText); Assert.IsTrue (attributes[0].HasAttribute (Consts.FrameworkAlternate)); Assert.AreEqual ("One;Two", attributes[0].GetAttribute (Consts.FrameworkAlternate)); } [Test] [Ignore("Unable to mock valid AssemblySet, ignore for now")] public void Attributes_Assembly_OtherAssembly () { var context = InitContext (string.Format (typeFrameXml, multiFrameworkXml), 2, forceAlignment: false); var fx = context.fx.Frameworks[1]; FrameworkTypeEntry typeEntry = fx.Types.First (); var attributeList = new[] { ((CustomAttribute)null, "One") }; // this is the 'second' fx, and we've changed the expected assembly name, // so the attribute, while it doesn't exist yet, shouldn't have an FX made since it doesn't exist in any other FX MDocUpdater.MakeAttributes( context.doc.FirstChild as XmlElement, attributeList, fx.IsFirstFrameworkForAssembly("one.dll"), fx.IsLastFrameworkForAssembly("one.dll"), () => fx.AllFrameworksStringWithAssembly("one.dll"), null, perLanguage: false); var attrNode = context.doc.FirstChild.SelectSingleNode ("Attributes"); var attributes = attrNode.SelectNodes ("Attribute").Cast ().ToArray (); Assert.IsTrue (attributes.Count () == 1); Assert.AreEqual ("One", attributes[0].FirstChild.InnerText); Assert.IsTrue (attributes[0].HasAttribute (Consts.FrameworkAlternate)); } [Test] public void FxElementTest() { XmlDocument doc = new XmlDocument(); doc.LoadXml(@"old value"); var context = InitContext(string.Format(typeFrameXml, multiFrameworkXml), 0, forceAlignment: false); var fx = context.fx.Frameworks[0]; FrameworkTypeEntry typeEntry = fx.Types.First(); XmlElement parentx = doc.DocumentElement; DocUtils.AddElementWithFx( typeEntry, parentx, isFirst: typeEntry.Framework.IsFirstFrameworkForType(typeEntry), isLast: typeEntry.Framework.IsLastFrameworkForType(typeEntry), allfxstring: new Lazy(() => typeEntry.Framework.AllFrameworksWithType(typeEntry)), clear: parent => { parent.RemoveAll(); }, findExisting: parent => { return parent.SelectSingleNode("X") as XmlElement; }, addItem: parent => { var item = parent.OwnerDocument.CreateElement("X"); item.InnerText = "value"; parent.AppendChild(item); return item; }); Assert.AreEqual(1, parentx.ChildNodes.Count); Assert.AreEqual("value", parentx.ChildNodes[0].InnerText); Assert.AreEqual("One", parentx.ChildNodes[0].Attributes[0].Value); } [Test] public void FxElementTest_Two() { XmlDocument doc = new XmlDocument(); doc.LoadXml(@"old value"); var context = InitContext(string.Format(typeFrameXml, multiFrameworkXml), 0, forceAlignment: false); var fx = context.fx.Frameworks[1]; FrameworkTypeEntry typeEntry = fx.Types.First(); XmlElement parentx = doc.DocumentElement; System.Func runfx = (te, value) => { DocUtils.AddElementWithFx( te, parentx, isFirst: te.Framework.IsFirstFrameworkForType(te), isLast: te.Framework.IsLastFrameworkForType(te), allfxstring: new Lazy(() => typeEntry.Framework.AllFrameworksWithType(typeEntry)), clear: parent => { parent.RemoveAll(); }, findExisting: parent => { return parent.ChildNodes.Cast().SingleOrDefault(e => e.Name == "X" && e.Value == value); }, addItem: parent => { var item = parent.OwnerDocument.CreateElement("X"); item.InnerText = value; parent.AppendChild(item); return item; }); return true; }; runfx(context.fx.Frameworks[0].Types.First(), "one"); runfx(context.fx.Frameworks[1].Types.First(), "two"); Assert.AreEqual(parentx.ChildNodes.Count, 2); Assert.IsTrue(parentx.ChildNodes.Cast().Any(e => e.HasAttribute(Consts.FrameworkAlternate)), "fx check"); } [Test] public void FxElementTest_Three() { XmlDocument doc = new XmlDocument(); doc.LoadXml(@"old value"); var context = InitContext(string.Format(typeFrameXml, multiFrameworkXml), 2, forceAlignment: false); var fx = context.fx.Frameworks[1]; FrameworkTypeEntry typeEntry = fx.Types.First(); XmlElement parentx = doc.DocumentElement; System.Func runfx = (te) => { DocUtils.AddElementWithFx( te, parentx, isFirst: typeEntry.Framework.IsFirstFrameworkForType(typeEntry), isLast: typeEntry.Framework.IsLastFrameworkForType(typeEntry), allfxstring: new Lazy(() => typeEntry.Framework.AllFrameworksWithType(typeEntry)), clear: parent => { parent.RemoveAll(); }, findExisting: parent => { return parent.SelectSingleNode("X") as XmlElement; }, addItem: parent => { var item = parent.OwnerDocument.CreateElement("X"); item.InnerText = "value"; parent.AppendChild(item); return item; }); return true; }; runfx(context.fx.Frameworks[0].Types.First()); runfx(context.fx.Frameworks[1].Types.First()); runfx(context.fx.Frameworks[2].Types.First()); Assert.AreEqual(parentx.ChildNodes.Count, 1); } string Normalize(string xml, bool clearFx = false) { XmlDocument doc = new XmlDocument (); doc.LoadXml (xml); return doc.OuterXml; } string typeFrameXml = @"{0}"; #region MyClass XML string startingEmptyXml = @" Method System.Void To be added. To be added. "; string normalSingleXml = @" Method System.Void To be added. To be added. "; string multiFrameworkXml = @" Method System.Void To be added. To be added. "; string multiFrameworkAligned = @" Method System.Void To be added. To be added. "; #endregion string SigmultiFrameworkXml = @" "; string SigmultiFrameworkAligned = @" "; string SigRegular = @" "; string SigRegularChanged = @" "; string SigRegularAllAligned = @" "; private ParamContext InitComplexContext(string methodXml, string ns, string methodName, FrameworkIndex fx) { var doc = new XmlDocument(); doc.LoadXml(methodXml); var beforeXML = doc.OuterXml; TypeDefinition type = GetDefinition(ns); var method = type.Methods.First(m => m.Name == methodName) as MethodReference; var updater = new MDocUpdater(); return new ParamContext() { doc = doc, beforeXML = beforeXML, method = method, parameters = method.Parameters.ToList(), fx = fx, updater = updater }; } private ParamContext InitContext (string methodXml, int fxIndex, bool forceAlignment=false, string ns1="mdoc.Test", string ns2="mdoc.Test2") { Func indexCheck = fi => fi < 2; if (typeof(T) == typeof(MyClass2)) indexCheck = fi => fi != 1; bool useFirst = forceAlignment || indexCheck(fxIndex); var doc = new XmlDocument (); //doc.PreserveWhitespace = true; doc.LoadXml (methodXml); var beforeXML = doc.OuterXml; XmlElement root = doc.SelectSingleNode ("//Docs") as XmlElement; // Docs TypeDefinition type = GetDefinition (ns1); var method = type.Methods.First (m => m.Name == "Meth") as MethodReference; var parameters = method.Parameters.ToList (); TypeDefinition type2 = GetDefinition (ns2); var method2 = type2.Methods.First (m => m.Name == "Meth") as MethodReference; var parameters2 = method2.Parameters.ToList (); // updater var updater = new MDocUpdater (); var fx = new FrameworkIndex ("", 3, null); fx.Frameworks.Add (new FrameworkEntry (fx.Frameworks, fx.Frameworks) { Id = "One", Name = "One", Replace=ns2, With=ns1 }); fx.Frameworks.Add (new FrameworkEntry (fx.Frameworks, fx.Frameworks) { Id = "Three", Name = "Three", Replace = ns2, With = ns1 }); fx.Frameworks.Add (new FrameworkEntry (fx.Frameworks, fx.Frameworks) { Id = "Two", Name = "Two", Replace = ns2, With = ns1 }); var i = 0; foreach (var f in fx.Frameworks) { if (indexCheck(i) || forceAlignment) { var t = f.ProcessType (type, type.Module.Assembly); t.ProcessMember (method); var aset = new AssemblySet (new[] { "one.dll" }); f.AddAssemblySet (aset); } else { var t = f.ProcessType (type2, type2.Module.Assembly); t.ProcessMember (method2); } i++; } updater.InitializeFrameworksCache (fx); return new ParamContext () { doc = doc, beforeXML = beforeXML, method = useFirst ? method : method2, parameters = useFirst ? parameters : parameters2, fx = fx, updater = updater }; } TypeDefinition GetDefinition(string ns) { Type t = typeof (T); string path = t.Assembly.Location; AssemblyDefinition assembly = AssemblyDefinition.ReadAssembly (path); return assembly.MainModule.Types.First (type => type.Name == t.Name && type.Namespace == ns); } } }