Merge pull request #205 from m3rlinez/master
[mono.git] / mcs / nunit24 / ClientUtilities / util / XmlResultVisitor.cs
1 // ****************************************************************\r
2 // This is free software licensed under the NUnit license. You\r
3 // may obtain a copy of the license as well as information regarding\r
4 // copyright ownership at http://nunit.org/?p=license&r=2.4.\r
5 // ****************************************************************\r
6 \r
7 namespace NUnit.Util\r
8 {\r
9         using System;\r
10         using System.Globalization;\r
11         using System.IO;\r
12         using System.Xml;\r
13         using System.Reflection;\r
14         using NUnit.Core;\r
15 \r
16         /// <summary>\r
17         /// Summary description for XmlResultVisitor.\r
18         /// </summary>\r
19         public class XmlResultVisitor : ResultVisitor\r
20         {\r
21                 private XmlTextWriter xmlWriter;\r
22                 private TextWriter writer;\r
23                 private MemoryStream memoryStream;\r
24 \r
25                 public XmlResultVisitor(string fileName, TestResult result)\r
26                 {\r
27                         xmlWriter = new XmlTextWriter( new StreamWriter(fileName, false, System.Text.Encoding.UTF8) );\r
28                         Initialize(result);\r
29                 }\r
30 \r
31         public XmlResultVisitor( TextWriter writer, TestResult result )\r
32                 {\r
33                         this.memoryStream = new MemoryStream();\r
34                         this.writer = writer;\r
35                         this.xmlWriter = new XmlTextWriter( new StreamWriter( memoryStream, System.Text.Encoding.UTF8 ) );\r
36                         Initialize( result );\r
37                 }\r
38 \r
39                 private void Initialize(TestResult result) \r
40                 {\r
41                         ResultSummarizer summaryResults = new ResultSummarizer(result);\r
42 \r
43                         xmlWriter.Formatting = Formatting.Indented;\r
44                         xmlWriter.WriteStartDocument(false);\r
45                         xmlWriter.WriteComment("This file represents the results of running a test suite");\r
46 \r
47                         xmlWriter.WriteStartElement("test-results");\r
48 \r
49                         xmlWriter.WriteAttributeString("name", summaryResults.Name);\r
50                         xmlWriter.WriteAttributeString("total", summaryResults.ResultCount.ToString());\r
51                         xmlWriter.WriteAttributeString("failures", summaryResults.FailureCount.ToString());\r
52                         xmlWriter.WriteAttributeString("not-run", summaryResults.TestsNotRun.ToString());\r
53 \r
54                         DateTime now = DateTime.Now;\r
55                         xmlWriter.WriteAttributeString("date", XmlConvert.ToString( now, "yyyy-MM-dd" ) );\r
56                         xmlWriter.WriteAttributeString("time", XmlConvert.ToString( now, "HH:mm:ss" ));\r
57                         WriteEnvironment();\r
58                         WriteCultureInfo();\r
59                 }\r
60 \r
61                 private void WriteCultureInfo() {\r
62                         xmlWriter.WriteStartElement("culture-info");\r
63                         xmlWriter.WriteAttributeString("current-culture",\r
64                                                        CultureInfo.CurrentCulture.ToString());\r
65                         xmlWriter.WriteAttributeString("current-uiculture",\r
66                                                        CultureInfo.CurrentUICulture.ToString());\r
67                         xmlWriter.WriteEndElement();\r
68                 }\r
69 \r
70                 private void WriteEnvironment() {\r
71                         xmlWriter.WriteStartElement("environment");\r
72                         xmlWriter.WriteAttributeString("nunit-version", \r
73                                                                                    Assembly.GetExecutingAssembly().GetName().Version.ToString());\r
74                         xmlWriter.WriteAttributeString("clr-version", \r
75                                                        Environment.Version.ToString());\r
76                         xmlWriter.WriteAttributeString("os-version",\r
77                                                        Environment.OSVersion.ToString());\r
78                         xmlWriter.WriteAttributeString("platform",\r
79                                 Environment.OSVersion.Platform.ToString());\r
80                         xmlWriter.WriteAttributeString("cwd",\r
81                                                        Environment.CurrentDirectory);\r
82                         xmlWriter.WriteAttributeString("machine-name",\r
83                                                        Environment.MachineName);\r
84                         xmlWriter.WriteAttributeString("user",\r
85                                                        Environment.UserName);\r
86                         xmlWriter.WriteAttributeString("user-domain",\r
87                                                        Environment.UserDomainName);\r
88                         xmlWriter.WriteEndElement();\r
89                 }\r
90 \r
91                 public void Visit(TestCaseResult caseResult) \r
92                 {\r
93                         xmlWriter.WriteStartElement("test-case");\r
94                         xmlWriter.WriteAttributeString("name",caseResult.Name);\r
95 \r
96                         if(caseResult.Description != null)\r
97                                 xmlWriter.WriteAttributeString("description", caseResult.Description);\r
98 \r
99                         xmlWriter.WriteAttributeString("executed", caseResult.Executed.ToString());\r
100                         if(caseResult.Executed)\r
101                         {\r
102                                 xmlWriter.WriteAttributeString("success", caseResult.IsSuccess.ToString() );\r
103 \r
104                                 xmlWriter.WriteAttributeString("time", caseResult.Time.ToString("#####0.000", NumberFormatInfo.InvariantInfo));\r
105 \r
106                                 xmlWriter.WriteAttributeString("asserts", caseResult.AssertCount.ToString() );\r
107                                 WriteCategories(caseResult);\r
108                                 WriteProperties(caseResult);\r
109                                 if(caseResult.IsFailure)\r
110                                 {\r
111                                         if(caseResult.IsFailure)\r
112                                                 xmlWriter.WriteStartElement("failure");\r
113                                         else\r
114                                                 xmlWriter.WriteStartElement("error");\r
115                                 \r
116                                         xmlWriter.WriteStartElement("message");\r
117                                         xmlWriter.WriteCData( EncodeCData( caseResult.Message ) );\r
118                                         xmlWriter.WriteEndElement();\r
119                                 \r
120                                         xmlWriter.WriteStartElement("stack-trace");\r
121                                         if(caseResult.StackTrace != null)\r
122                                                 xmlWriter.WriteCData( EncodeCData( StackTraceFilter.Filter( caseResult.StackTrace ) ) );\r
123                                         xmlWriter.WriteEndElement();\r
124                                 \r
125                                         xmlWriter.WriteEndElement();\r
126                                 }\r
127                                 \r
128                         }\r
129                         else\r
130                         {\r
131                                 WriteCategories(caseResult);\r
132                                 WriteProperties(caseResult);\r
133                                 xmlWriter.WriteStartElement("reason");\r
134                                 xmlWriter.WriteStartElement("message");\r
135                                 xmlWriter.WriteCData(caseResult.Message);\r
136                                 xmlWriter.WriteEndElement();\r
137                                 xmlWriter.WriteEndElement();\r
138                         }\r
139             \r
140                         xmlWriter.WriteEndElement();\r
141                 }\r
142 \r
143                 /// <summary>\r
144                 /// Makes string safe for xml parsing, replacing control chars with '?'\r
145                 /// </summary>\r
146                 /// <param name="encodedString">string to make safe</param>\r
147                 /// <returns>xml safe string</returns>\r
148                 private static string CharacterSafeString(string encodedString)\r
149                 {\r
150                         /*The default code page for the system will be used.\r
151                         Since all code pages use the same lower 128 bytes, this should be sufficient\r
152                         for finding uprintable control characters that make the xslt processor error.\r
153                         We use characters encoded by the default code page to avoid mistaking bytes as\r
154                         individual characters on non-latin code pages.*/\r
155                         char[] encodedChars = System.Text.Encoding.Default.GetChars(System.Text.Encoding.Default.GetBytes(encodedString));\r
156                         \r
157                         System.Collections.ArrayList pos = new System.Collections.ArrayList();\r
158                         for(int x = 0 ; x < encodedChars.Length ; x++)\r
159                         {\r
160                                 char currentChar = encodedChars[x];\r
161                                 //unprintable characters are below 0x20 in Unicode tables\r
162                                 //some control characters are acceptable. (carriage return 0x0D, line feed 0x0A, horizontal tab 0x09)\r
163                                 if(currentChar < 32 && (currentChar != 9 && currentChar != 10 && currentChar != 13))\r
164                                 {\r
165                                         //save the array index for later replacement.\r
166                                         pos.Add(x);\r
167                                 }\r
168                         }\r
169                         foreach(int index in pos)\r
170                         {\r
171                                 encodedChars[index] = '?';//replace unprintable control characters with ?(3F)\r
172                         }\r
173                         return System.Text.Encoding.Default.GetString(System.Text.Encoding.Default.GetBytes(encodedChars));\r
174                 }\r
175 \r
176                 private string EncodeCData( string text )\r
177                 {\r
178                         return CharacterSafeString( text ).Replace( "]]>", "]]&gt;" );\r
179                 }\r
180 \r
181                 public void WriteCategories(TestResult result)\r
182                 {\r
183                         if (result.Test.Categories != null && result.Test.Categories.Count > 0)\r
184                         {\r
185                                 xmlWriter.WriteStartElement("categories");\r
186                                 foreach (string category in result.Test.Categories)\r
187                                 {\r
188                                         xmlWriter.WriteStartElement("category");\r
189                                         xmlWriter.WriteAttributeString("name", category);\r
190                                         xmlWriter.WriteEndElement();\r
191                                 }\r
192                                 xmlWriter.WriteEndElement();\r
193                         }\r
194                 }\r
195 \r
196                 public void WriteProperties(TestResult result)\r
197                 {\r
198                         if (result.Test.Properties != null && result.Test.Properties.Count > 0)\r
199                         {\r
200                                 xmlWriter.WriteStartElement("properties");\r
201                                 foreach (string key in result.Test.Properties.Keys)\r
202                                 {\r
203                                         xmlWriter.WriteStartElement("property");\r
204                                         xmlWriter.WriteAttributeString("name", key);\r
205                                         xmlWriter.WriteAttributeString("value", result.Test.Properties[key].ToString() );\r
206                                         xmlWriter.WriteEndElement();\r
207                                 }\r
208                                 xmlWriter.WriteEndElement();\r
209                         }\r
210                 }\r
211 \r
212                 public void Visit(TestSuiteResult suiteResult) \r
213                 {\r
214                         xmlWriter.WriteStartElement("test-suite");\r
215                         xmlWriter.WriteAttributeString("name",suiteResult.Name);\r
216                         if(suiteResult.Description != null)\r
217                                 xmlWriter.WriteAttributeString("description", suiteResult.Description);\r
218 \r
219                         xmlWriter.WriteAttributeString("success", suiteResult.IsSuccess.ToString());\r
220                         xmlWriter.WriteAttributeString("time", suiteResult.Time.ToString("#####0.000", NumberFormatInfo.InvariantInfo));\r
221                         xmlWriter.WriteAttributeString("asserts", suiteResult.AssertCount.ToString() );\r
222          \r
223                         WriteCategories(suiteResult);\r
224                         WriteProperties(suiteResult);\r
225 \r
226                         if ( suiteResult.IsFailure && suiteResult.FailureSite == FailureSite.SetUp )\r
227                         {\r
228                                 xmlWriter.WriteStartElement("failure");\r
229 \r
230                                 xmlWriter.WriteStartElement("message");\r
231                                 xmlWriter.WriteCData( EncodeCData( suiteResult.Message ) );\r
232                                 xmlWriter.WriteEndElement();\r
233 \r
234                                 xmlWriter.WriteStartElement("stack-trace");\r
235                                 if(suiteResult.StackTrace != null)\r
236                                         xmlWriter.WriteCData( EncodeCData( StackTraceFilter.Filter( suiteResult.StackTrace ) ) );\r
237                                 xmlWriter.WriteEndElement();\r
238 \r
239                                 xmlWriter.WriteEndElement();\r
240                         }\r
241 \r
242                         xmlWriter.WriteStartElement("results");                  \r
243                         foreach (TestResult result in suiteResult.Results)\r
244                         {\r
245                                 result.Accept(this);\r
246                         }\r
247                         xmlWriter.WriteEndElement();\r
248 \r
249                         xmlWriter.WriteEndElement();\r
250                 }\r
251 \r
252                 public void Write()\r
253                 {\r
254                         try \r
255                         {\r
256                                 xmlWriter.WriteEndElement();\r
257                                 xmlWriter.WriteEndDocument();\r
258                                 xmlWriter.Flush();\r
259 \r
260                                 if ( memoryStream != null && writer != null )\r
261                                 {\r
262                                         memoryStream.Position = 0;\r
263                                         using ( StreamReader rdr = new StreamReader( memoryStream ) )\r
264                                         {\r
265                                                 writer.Write( rdr.ReadToEnd() );\r
266                                         }\r
267                                 }\r
268 \r
269                                 xmlWriter.Close();\r
270                         } \r
271                         finally \r
272                         {\r
273                                 //writer.Close();\r
274                         }\r
275                 }\r
276         }\r
277 }\r