New test.
[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 abstract class XmlComparableTest
44         {
45                 public abstract bool XmlCompare(XmlDocument d1, XmlDocument d2, bool ignoreAlmost);
46         }
47
48         public class HtmlDiff : XmlComparableTest
49         {
50                 public const string BEGIN_TAG = "begint";
51                 public const string END_TAG = "endt";
52
53                 private XmlDocument _xmlIgnoreList = null;
54                 private string _compareStatus = "";
55                 private static string _compareActual = "";
56                 private static string _compareExpect = "";
57                 private string _ignoreListFile = "";
58
59                 
60
61                 public HtmlDiff()
62                 {
63                 }
64
65                 public string IgnoreListFile
66                 {
67                         get {return _ignoreListFile;}
68                         set {_ignoreListFile = value;}
69                 }
70
71                 public string CompareStatus
72                 {
73                         get {return _compareStatus.ToString();}
74                 }
75
76                 public static string GetControlFromPageHtml (string str)
77                 {
78                         if (str == null || str == string.Empty)
79                                 throw new ArgumentException ("internal error: str is null or empty");
80                         int beginPos = str.IndexOf (BEGIN_TAG);
81                         int endPos = str.IndexOf (END_TAG);
82                         if (beginPos == -1)
83                                 throw new Exception ("internal error: BEGIN_TAG is missing. Full source: "+str);
84                         if (endPos == -1)
85                                 throw new Exception ("internal error: END_TAG is missing. Full source: "+str);
86                                 
87                         StringBuilder sb = new StringBuilder ();
88                         sb.Append (str.Substring (beginPos + BEGIN_TAG.Length, endPos - beginPos - BEGIN_TAG.Length));
89                         return sb.ToString ();
90                 }
91
92                 public static void AssertAreEqual (string origin, string derived, string msg)
93                 {
94                         bool test = HtmlComparer (origin, derived);
95                         if (!test) {\r
96                                 Assert.AreEqual (_compareExpect, _compareActual, msg);
97                                        
98                         }
99                 }
100
101                 public static bool HtmlComparer (string origin, string derived)
102                 {
103                         XmlDocument or = new XmlDocument ();
104                         MonoTests.stand_alone.WebHarness.HtmlDiff helper = new MonoTests.stand_alone.WebHarness.HtmlDiff ();
105                         or.LoadXml (helper.HtmltoXml (origin));
106                         XmlDocument dr = new XmlDocument ();
107                         dr.LoadXml (helper.HtmltoXml (derived));
108                         return helper.XmlCompare (or, dr, false);
109                 }
110
111                 public override bool XmlCompare(XmlDocument expected, XmlDocument actual, bool ignoreAlmost)
112                 {
113                         XmlComparer comparer = new XmlComparer();
114                         if (ignoreAlmost == false)
115                         {
116                                 DoAlmost(expected);
117                                 DoAlmost(actual);
118                         }
119                         bool c = comparer.AreEqual(expected, actual);
120                         _compareStatus = comparer.LastCompare;
121                         _compareActual = comparer.Actual;
122                         _compareExpect = comparer.Expected;
123                         return c;
124                 }
125
126                 public string HtmltoXml(string html)
127                 {
128                         HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();\r
129                         doc.LoadHtml (html.Trim (new char [] { '\r', '\n', ' ' })); // bug in HtmlAgilityPack
130
131                         StringBuilder fixedxml = new StringBuilder();
132                         StringWriter sw = new StringWriter(fixedxml);
133
134                         try
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                                 {
152                                         if (n.Attributes["style"] != null)
153                                         {
154                                                 string att = n.Attributes["style"].Value;
155                                                 string [] style = att.Trim(new char[]{' ', ';'}).Split(';');
156
157                                                 for (int styleIndex=0; styleIndex<style.Length; styleIndex++)
158                                                 {
159                                                         style[styleIndex] = FixStyleNameValue(style[styleIndex]);
160                                                 }
161                                                 Array.Sort(style);
162                                                 n.Attributes["style"].Value = string.Join(";", style);
163                                         }
164                                 }
165                                 tempDoc.Save(sw);
166                         }
167                         catch (Exception)
168                         {
169                                 Console.WriteLine("Error parsing html response...");
170                                 Console.WriteLine("Test case aborted");
171                                 return "<TestCaseAborted></TestCaseAborted>";
172                         }
173                         return fixedxml.ToString();
174                 }
175
176                 private string FixStyleNameValue(string nameValue)
177                 {
178                         string [] nv = nameValue.Split(':');
179                         // value may contain spaces in case of
180                         // multiple values for one key
181                         string [] nvalue = nv[1].Trim().Split(' ');
182                         Array.Sort(nvalue);
183                         nv[1] = string.Join(" ", nvalue);
184                         return nv[0].Trim().ToLower() + ":" + nv[1].Trim().ToLower();
185                 }
186
187                 private void DoAlmost(XmlDocument xmlDocument)
188                 {
189                         XmlNode XmlIgnoreNode;
190                         IEnumerator xmlIgnoreEnum;
191
192
193                         if (_xmlIgnoreList == null)
194                         {
195                                 _xmlIgnoreList = new XmlDocument();
196                                 string xml;\r
197 \r
198                                 Stream source = Assembly.GetExecutingAssembly ()\r
199                                         .GetManifestResourceStream ("HtmlCompare.nunitweb_config.xml");\r
200                                 if (source == null) {\r
201                                         source = Assembly.GetExecutingAssembly ()\r
202                                         .GetManifestResourceStream ("nunitweb_config.xml");\r
203                                 }\r
204                                                                 \r
205                                 try {\r
206                                         using (StreamReader sr = new StreamReader (source))\r
207                                                 xml = sr.ReadToEnd ();\r
208                                 }\r
209                                 finally {\r
210                                         source.Close ();\r
211                                 }\r
212                                 \r
213                                 _xmlIgnoreList.LoadXml (xml);
214                         }
215                         // Remove by Id or Name
216                         // search by tag and if id or name match, remove all attributes
217                         // must be the first almost since the following almost delete the id and name
218                         
219                         xmlIgnoreEnum = _xmlIgnoreList.SelectSingleNode("Almost/RemoveById").GetEnumerator();
220                         while (xmlIgnoreEnum.MoveNext())
221                         {
222                                 XmlNodeList DocNodeList;
223                                 XmlIgnoreNode = (XmlNode)xmlIgnoreEnum.Current;
224                                 DocNodeList = xmlDocument.GetElementsByTagName("*");
225                                 if (DocNodeList != null)
226                                 {
227                                         foreach (XmlElement tmpXmlElement in DocNodeList)
228                                         {
229                                                 foreach (XmlAttribute tmpIgnoreAttr in XmlIgnoreNode.Attributes)
230                                                 {
231                                                         if (tmpXmlElement.Name.ToLower() == XmlIgnoreNode.Name.ToLower()) 
232                                                         {
233                                                                 if (tmpXmlElement.Attributes[tmpIgnoreAttr.Name] != null )
234                                                                 {
235                                                                         if (tmpXmlElement.Attributes[tmpIgnoreAttr.Name].Value.ToLower() == tmpIgnoreAttr.Value.ToLower())
236                                                                         {
237                                                                                 tmpXmlElement.RemoveAllAttributes();
238                                                                         }
239                                                                 }
240                                                         }
241                                                 }
242                                         }
243                                 }       
244                         }
245                         // remove ignored attributes
246                         // search for tag and remove it's attributes
247                         xmlIgnoreEnum = _xmlIgnoreList.SelectSingleNode("Almost/IgnoreList").GetEnumerator(); //FirstChild.GetEnumerator
248                         while (xmlIgnoreEnum.MoveNext())
249                         {
250                                 XmlIgnoreNode = (XmlNode)xmlIgnoreEnum.Current;
251                                 XmlNodeList DocNodeList;
252                                 //clean specific element
253
254                                 DocNodeList = xmlDocument.GetElementsByTagName("*");
255                                 if (DocNodeList != null)
256                                 {
257                                         foreach (XmlElement tmpXmlElement in DocNodeList)
258                                         {
259                                                 if (tmpXmlElement.Name.ToLower() == XmlIgnoreNode.Name.ToLower()) 
260                                                 {
261                                                         foreach (XmlAttribute tmpIgnoreAttr in XmlIgnoreNode.Attributes)
262                                                         {
263                                                                 tmpXmlElement.RemoveAttribute(tmpIgnoreAttr.Name);
264                                                         }
265                                                 }
266                                         }
267                                 }
268                         }
269
270                         // clean javascript attribute value
271                         xmlIgnoreEnum = _xmlIgnoreList.SelectSingleNode("Almost/CleanJavaScriptValueList").GetEnumerator(); //FirstChild.GetEnumerator
272                         while (xmlIgnoreEnum.MoveNext())
273                         {
274                                 XmlIgnoreNode = (XmlNode)xmlIgnoreEnum.Current;
275                                 XmlNodeList DocNodeList;
276                                 //clean Java Script attribute values
277                                 DocNodeList = xmlDocument.GetElementsByTagName("*");
278                                 if (DocNodeList != null)
279                                 {
280                                         foreach (XmlElement tmpXmlElement in DocNodeList)
281                                         {
282                                                 if (tmpXmlElement.Name.ToLower() == XmlIgnoreNode.Name.ToLower()) 
283                                                 {
284                                                         foreach (XmlAttribute tmpIgnoreAttr in XmlIgnoreNode.Attributes)
285                                                         {
286                                                                 if (tmpXmlElement.Attributes[tmpIgnoreAttr.Name] != null )
287                                                                 {
288                                                                         if (tmpXmlElement.Attributes[tmpIgnoreAttr.Name].Value.ToLower().IndexOf("javascript") >= 0 )
289                                                                         {
290                                                                                 tmpXmlElement.SetAttribute(tmpIgnoreAttr.Name, "");
291                                                                         }
292                                                                 }
293                                                         }
294                                                 }
295                                         }
296                                 }
297                         }
298                 }
299         }
300 }