Grasshopper now uses csproj instead of vmwcsproj
[mono.git] / mcs / class / System.Web / Test / mainsoft / MainsoftWebTest / NunitWebTest.cs
1 //
2 // Authors:
3 //   Rafael Mizrahi   <rafim@mainsoft.com>
4 //   Erez Lotan       <erezl@mainsoft.com>
5 //   Vladimir Krasnov <vladimirk@mainsoft.com>
6 //   
7 // 
8 // Copyright (c) 2002-2005 Mainsoft Corporation.
9 // 
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
17 // 
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 // 
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 //
29
30
31
32 using System;
33 using System.IO;
34 using System.Xml;
35 using System.Net;
36 using System.Text;
37 using System.Collections;
38 using System.Reflection;
39 using NUnit.Framework;
40
41 namespace MonoTests.stand_alone.WebHarness
42 {
43         public class HtmlDiff
44         {
45                 public const string BEGIN_TAG = "begint";
46                 public const string END_TAG = "endt";
47
48                 private XmlDocument _xmlIgnoreList = null;
49                 private string _compareStatus = "";
50                 private static string _compareActual = "";
51                 private static string _compareExpect = "";
52                 private string _ignoreListFile = "";
53
54                 
55
56                 public HtmlDiff()
57                 {
58                 }
59
60                 public string IgnoreListFile
61                 {
62                         get {return _ignoreListFile;}
63                         set {_ignoreListFile = value;}
64                 }
65
66                 public string CompareStatus
67                 {
68                         get {return _compareStatus.ToString();}
69                 }
70
71                 public static string GetControlFromPageHtml (string str)
72                 {
73                         if (str == null || str == string.Empty)
74                                 throw new ArgumentException ("internal error: str is null or empty");
75                         int beginPos = str.IndexOf (BEGIN_TAG);
76                         int endPos = str.IndexOf (END_TAG);
77                         if (beginPos == -1)
78                                 throw new Exception ("internal error: BEGIN_TAG is missing. Full source: "+str);
79                         if (endPos == -1)
80                                 throw new Exception ("internal error: END_TAG is missing. Full source: "+str);
81                                 
82                         StringBuilder sb = new StringBuilder ();
83                         sb.Append (str.Substring (beginPos + BEGIN_TAG.Length, endPos - beginPos - BEGIN_TAG.Length));
84                         return sb.ToString ();
85                 }
86
87                 public static void AssertAreEqual (string origin, string derived, string msg)
88                 {
89                         bool test = false;
90                         try {
91                                 test = HtmlComparer (origin, derived);
92                         }
93                         catch (Exception e) {
94                                 //swallow e when there is XML error and fallback
95                                 //to the text comparison
96                                 Assert.AreEqual (origin, derived, msg);
97                         }
98                         if (!test) {
99                                 Assert.AreEqual (_compareExpect, _compareActual, msg);
100                         }
101                 }
102
103                 private static bool HtmlComparer (string origin, string derived)
104                 {
105                         XmlDocument or = new XmlDocument ();
106                         MonoTests.stand_alone.WebHarness.HtmlDiff helper = new MonoTests.stand_alone.WebHarness.HtmlDiff ();
107                         or.LoadXml (helper.HtmltoXml (origin));
108                         XmlDocument dr = new XmlDocument ();
109                         dr.LoadXml (helper.HtmltoXml (derived));
110                         return helper.XmlCompare (or, dr, false);
111                 }
112
113                 private bool XmlCompare(XmlDocument expected, XmlDocument actual, bool ignoreAlmost)
114                 {
115                         XmlComparer comparer = new XmlComparer();
116                         if (ignoreAlmost == false)
117                         {
118                                 DoAlmost(expected);
119                                 DoAlmost(actual);
120                         }
121                         bool c = comparer.AreEqual(expected, actual);
122                         _compareStatus = comparer.LastCompare;
123                         _compareActual = comparer.Actual;
124                         _compareExpect = comparer.Expected;
125                         return c;
126                 }
127
128                 public string HtmltoXml (string html) //throws XmlException
129                 {
130                         HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument ();
131                         doc.LoadHtml (html.Trim (new char[] { '\r', '\n', ' ' })); // bug in HtmlAgilityPack
132
133                         StringBuilder fixedxml = new StringBuilder ();
134                         StringWriter sw = new StringWriter (fixedxml);
135
136                         StringBuilder tempxml = new StringBuilder ();
137                         StringWriter tsw = new StringWriter (tempxml);
138
139                         doc.OptionOutputAsXml = true;
140                         doc.Save (tsw);
141
142                         // fix style attribute
143                         // the reason is that style attribute name-value pairs come in different order
144                         // in .NET and GH
145                         // Here I will sort the values of style attribute
146                         XmlDocument tempDoc = new XmlDocument ();
147                         tempDoc.LoadXml (tempxml.ToString ());
148
149                         XmlNodeList allNodes = tempDoc.SelectNodes ("//*");
150                         foreach (XmlNode n in allNodes) {
151                                 if (n.Attributes["style"] != null) {
152                                         string att = n.Attributes["style"].Value;
153                                         string[] style = att.Trim (new char[] { ' ', ';' }).Split (';');
154
155                                         for (int styleIndex = 0; styleIndex < style.Length; styleIndex++) {
156                                                 style[styleIndex] = FixStyleNameValue (style[styleIndex]);
157                                         }
158                                         Array.Sort (style);
159                                         n.Attributes["style"].Value = string.Join (";", style);
160                                 }
161                         }
162                         tempDoc.Save (sw);
163                         return fixedxml.ToString ();
164                 }
165
166                 private string FixStyleNameValue(string nameValue)
167                 {
168                         string [] nv = nameValue.Split(':');
169                         // value may contain spaces in case of
170                         // multiple values for one key
171                         string [] nvalue = nv[1].Trim().Split(' ');
172                         Array.Sort(nvalue);
173                         nv[1] = string.Join(" ", nvalue);
174                         return nv[0].Trim().ToLower() + ":" + nv[1].Trim().ToLower();
175                 }
176
177                 private void DoAlmost(XmlDocument xmlDocument)
178                 {
179                         XmlNode XmlIgnoreNode;
180                         IEnumerator xmlIgnoreEnum;
181
182
183                         if (_xmlIgnoreList == null)
184                         {
185                                 _xmlIgnoreList = new XmlDocument();
186                                 string xml;
187
188                                 Stream source = Assembly.GetExecutingAssembly ()
189                                         .GetManifestResourceStream ("HtmlCompare.nunitweb_config.xml");
190                                 if (source == null) {
191                                         source = Assembly.GetExecutingAssembly ()
192                                         .GetManifestResourceStream ("nunitweb_config.xml");
193                                 }
194                                                                 
195                                 try {
196                                         using (StreamReader sr = new StreamReader (source))
197                                                 xml = sr.ReadToEnd ();
198                                 }
199                                 finally {
200                                         source.Close ();
201                                 }
202                                 
203                                 _xmlIgnoreList.LoadXml (xml);
204                         }
205                         // Remove by Id or Name
206                         // search by tag and if id or name match, remove all attributes
207                         // must be the first almost since the following almost delete the id and name
208                         
209                         xmlIgnoreEnum = _xmlIgnoreList.SelectSingleNode("Almost/RemoveById").GetEnumerator();
210                         while (xmlIgnoreEnum.MoveNext())
211                         {
212                                 XmlNodeList DocNodeList;
213                                 XmlIgnoreNode = (XmlNode)xmlIgnoreEnum.Current;
214                                 DocNodeList = xmlDocument.GetElementsByTagName("*");
215                                 if (DocNodeList != null)
216                                 {
217                                         foreach (XmlElement tmpXmlElement in DocNodeList)
218                                         {
219                                                 foreach (XmlAttribute tmpIgnoreAttr in XmlIgnoreNode.Attributes)
220                                                 {
221                                                         if (tmpXmlElement.Name.ToLower() == XmlIgnoreNode.Name.ToLower()) 
222                                                         {
223                                                                 if (tmpXmlElement.Attributes[tmpIgnoreAttr.Name] != null )
224                                                                 {
225                                                                         if (tmpXmlElement.Attributes[tmpIgnoreAttr.Name].Value.ToLower() == tmpIgnoreAttr.Value.ToLower())
226                                                                         {
227                                                                                 tmpXmlElement.RemoveAllAttributes();
228                                                                         }
229                                                                 }
230                                                         }
231                                                 }
232                                         }
233                                 }       
234                         }
235                         // remove ignored attributes
236                         // search for tag and remove it's attributes
237                         xmlIgnoreEnum = _xmlIgnoreList.SelectSingleNode("Almost/IgnoreList").GetEnumerator(); //FirstChild.GetEnumerator
238                         while (xmlIgnoreEnum.MoveNext())
239                         {
240                                 XmlIgnoreNode = (XmlNode)xmlIgnoreEnum.Current;
241                                 XmlNodeList DocNodeList;
242                                 //clean specific element
243
244                                 DocNodeList = xmlDocument.GetElementsByTagName("*");
245                                 if (DocNodeList != null)
246                                 {
247                                         foreach (XmlElement tmpXmlElement in DocNodeList)
248                                         {
249                                                 if (tmpXmlElement.Name.ToLower() == XmlIgnoreNode.Name.ToLower()) 
250                                                 {
251                                                         foreach (XmlAttribute tmpIgnoreAttr in XmlIgnoreNode.Attributes)
252                                                         {
253                                                                 tmpXmlElement.RemoveAttribute(tmpIgnoreAttr.Name);
254                                                         }
255                                                 }
256                                         }
257                                 }
258                         }
259
260                         // clean javascript attribute value
261                         xmlIgnoreEnum = _xmlIgnoreList.SelectSingleNode("Almost/CleanJavaScriptValueList").GetEnumerator(); //FirstChild.GetEnumerator
262                         while (xmlIgnoreEnum.MoveNext())
263                         {
264                                 XmlIgnoreNode = (XmlNode)xmlIgnoreEnum.Current;
265                                 XmlNodeList DocNodeList;
266                                 //clean Java Script attribute values
267                                 DocNodeList = xmlDocument.GetElementsByTagName("*");
268                                 if (DocNodeList != null)
269                                 {
270                                         foreach (XmlElement tmpXmlElement in DocNodeList)
271                                         {
272                                                 if (tmpXmlElement.Name.ToLower() == XmlIgnoreNode.Name.ToLower()) 
273                                                 {
274                                                         foreach (XmlAttribute tmpIgnoreAttr in XmlIgnoreNode.Attributes)
275                                                         {
276                                                                 if (tmpXmlElement.Attributes[tmpIgnoreAttr.Name] != null )
277                                                                 {
278                                                                         if (tmpXmlElement.Attributes[tmpIgnoreAttr.Name].Value.ToLower().IndexOf("javascript") >= 0 )
279                                                                         {
280                                                                                 tmpXmlElement.SetAttribute(tmpIgnoreAttr.Name, "");
281                                                                         }
282                                                                 }
283                                                         }
284                                                 }
285                                         }
286                                 }
287                         }
288                 }
289         }
290 }